Kafka核心元件之協調器
協調器介紹
kafka引入協調器有其歷史過程,原來consumer資訊依賴於zookeeper儲存,當代理或消費者發生變化時,引發消費者平衡,此時消費者之間是互不透明的,每個消費者和zookeeper單獨通訊,容易造成羊群效應和腦裂問題。
為了解決這些問題,kafka引入了協調器:
- 消費者端引入消費者協調器(ConsumerCoordinator)
每個consumer例項化時,都會建立ConsumerCoordinator例項,負責同一個消費組下各個消費者和服務端組協調器之間的通訊。 - 服務端引入組協調器(GroupCoordinator)
每個broker啟動的時候,都會建立GroupCoordinator例項,管理部分消費組(叢集負載均衡)和組下每個消費者消費的偏移量(offset)
消費者協調器
消費者協調器,可以看作是消費者做操作的代理類(其實並不是),消費者很多操作通過消費者協調器進行處理。
消費者協調器主要負責如下工作:
- 更新消費者快取的MetaData
- 向組協調器申請加入組
- 消費者加入組後的相應處理
- 請求離開消費組
- 向組協調器提交偏移量
- 通過心跳,保持組協調器的連線感知
- 被組協調器選為leader的消費者的協調器,負責消費者分割槽分配。分配結果傳送給組協調器
- 非leader的消費者,通過消費者協調器和組協調器同步分配結果
組協調器
組協調器負責處理消費者協調器發過來的各種請求。
組協調器主要提供如下功能:
- 在與之連線的消費者中選舉出消費者leader
- 下發leader消費者返回的消費者分割槽分配結果給所有的消費者
- 管理消費者的消費偏移量提交,儲存在kafka的內部主題中
- 和消費者心跳保持,知道哪些消費者已經死掉,組中存活的消費者是哪些
消費偏移量管理
消費者消費時,會在本地維護消費到的位置(offset),就是偏移量,這樣下次消費才知道從哪裡開始消費。如果整個環境沒有變化,這樣做就足夠了。但一旦消費者平衡操作或者分割槽變化後,消費者不再對應原來的分割槽,而每個消費者的offset也沒有同步到伺服器,這樣就無法接著前任的工作繼續進行了。
因此只有把消費偏移量定期傳送到伺服器,由GroupCoordinator集中式管理,分割槽重分配後,各個消費者從GroupCoordinator讀取自己對應分割槽的offset,在新的分割槽上繼續前任的工作。
Consumer Rebalance機制
對於 Consumer Group 來說,可能隨時都會有 Consumer 加入或退出,那麼 Consumer 列表的變化必定會引起 Partition 的重新分配,這個分配過程就叫做 Consumer Rebalance。
觸發消費者rebalance的常見情況:
- consumer所在服務重啟或宕機
- 動態給topic增加了分割槽
- 消費組訂閱了更多的topic
Rebalance過程
第一階段:選擇組協調器
每個consumer group都會選擇一個broker作為自己的組協調器coordinator,負責監控這個消費組裡的所有消費者的心跳,以及判斷是否宕機,然後開啟消費者rebalance。
consumer group中的每個consumer啟動時會向kafka叢集中的某個節點發送FindCoordinatorRequest請求來查詢對應的組協調器GroupCoordinator,並跟其建立網路連線。
組協調器選擇方式:
通過如下公式可以選出consumer消費的offset要提交到__consumer_offsets的哪個分割槽,這個分割槽leader對應的broker就是這個consumer group的coordinator.
公式:
hash(consumer group id) % __consumer_offsets主題的分割槽數
第二階段:加入消費組JOIN GROUP
在成功找到消費組所對應的GroupCoordinator之後就進入加入消費組的階段,在此階段的消費者會向GroupCoordinator傳送JoinGroupRequest請求,並處理響應。
然後GroupCoordinator從一個consumer group中選擇第一個加入group的consumer作為leader(消費組協調器),把consumer group情況傳送給這個leader,接著這個leader會負責制定分割槽方案。
第三階段:SYNC GROUP
consumer leader通過給GroupCoordinator傳送SyncGroupRequest,接著GroupCoordinator就把分割槽方案下發給各個consumer,他們會根據指定分割槽的leader broker進行網路連線以及訊息消費。
Rebalance分割槽分配策略
主要有三種rebalance的策略:range、round-robin、sticky。
預設情況為range分配策略,假設一個主題有10個分割槽(0-9),現在有三個consumer消費:
- range策略:按照分割槽序號排序
假設 n=分割槽數/消費者數量=3,m=分割槽數%消費者數量 = 1,那麼前m個消費者每個分配n+1個分割槽,後面的(消費者數量-m)個消費者每個分配n個分割槽。比如分割槽0-3給一個consumer,分割槽4-6給一個consumer,分割槽7-9給一個consumer。 - round-robin策略:輪詢分配
比如分割槽0、3、6、9給一個consumer,分割槽1、4、7給一個consumer,分割槽2、5、8給一個consumer。 - sticky策略:在rebalance的時候,需要保證如下兩個原則
- 分割槽的分配要儘可能均勻;
- 分割槽的分配儘可能與上次分配的保持相同。