Kafka 0.11版本新功能介紹 —— 空消費組延時rebalance
在0.11之前的版本中,多個consumer實例加入到一個空消費組將導致多次的rebalance,這是由於每個consumer instance啟動的時間不可控,很有可能超出coordinator確定的rebalance timeout(即max.poll.interval.ms),而每次rebalance的代價又相當地大,因為很多狀態都需要在rebalance前被持久化,而在rebalance後被重新初始化。曾經有個國外用戶,他有100個consumer,每次rebalance的時間甚至要1個小時以上!
對於目前版本的Kafka來說,consumer的rebalance的確有需要需要改進的部分,很容易想到的包括:
- 對於空消費組而言,能夠稍稍放松rebalance的嚴苛條件,讓rebalance發生的次數降低一些
- 對於有大量成員的消費組而言,是否可以考慮以前的分配方案而不是像現在這樣完全拋棄之前方案從頭來過
值得高興的是,社區已經實現了第一個改進並將其集成進0.11.0.0版本中,也就是說用戶在升級到0.11後便可以體驗到這種延時rebalance的效果,主要表現為空消費組從EMPTY到STABLE的時間間隔應該顯著縮短。本文將簡要介紹一下該新功能以及實現原理。
新增參數:group.initial.rebalance.delay.ms
對於用戶來說,這個改進最直接的效果就是新增了一個broker配置:group.initial.rebalance.delay.ms,默認是3秒鐘。用戶需要在server.properties文件中自行修改為想要配置的值。這個參數的主要效果就是讓coordinator推遲空消費組接收到成員加入請求後本應立即開啟的rebalance。在實際使用時,假設你預估你的所有consumer組成員加入需要在10s內完成,那麽你就可以設置該參數=10000。目前來看,這個參數的使用還是很方便的~
coordinator底層修改
為了實現這一功能,需要修改一些底層的設計。首先,對於消費組狀態而言,之前的文章中討論過,當前的狀態機如下圖所示:
由上圖可見,Empty到PreparingRebalance的轉化就是發生有成員加入之後。現在在這兩個狀態之間新增了一個狀態:InitialRebalance。那麽對於一個空的消費組而言,當第一個成員加入時,組狀態會進入到InitialRebalance,同時對這個JoinGroup請求的處理可能會推遲一段時間,但這段時間不會超過rebalance超時時間和group.initial.rebalance.delay.ms兩者的小者。之後倘若又有一個新成員加入組,那麽仍然按照之前的邏輯,組狀態是InitialRebalance,但此時這個請求被推遲的最大時間將會更新為min(剩下的rebalance超時時間,group.initial.rebalance.delay.ms)。這個剩余rebalane超時=初始rebalance超時- N * group.initial.rebalance.delay.ms,N表示前面已經發生過的N次成員加入。改進後的組狀態機如下圖所示:
當剩余rebalance超時變更成0時,即認為延時已經過期了,因此coordinator會將消費組狀態變更成PreparingRebalance,下面的事情就和之前的流程一致了。至於這些請求是如何在broker端被延時處理的,其實這也要歸功於DelayedJoin以及底層的purgatory機制了,有時間的話跟大家詳細說說它的設計。
Kafka 0.11版本新功能介紹 —— 空消費組延時rebalance