kafka rebalance解決方案 -incremental cooperative協議和static membership功能

語言: CN / TW / HK
在kafka2.4的時候,社群推出兩個新feature來解決重平衡過程中stop the world的問題。1. Incremental Rebalance Protocol(以下簡稱cooperative協議):改進了eager協議(即舊重平衡協議)的問題,避免STW的發生2. static membership:避免重起或暫時離開的消費者觸發重平衡本篇接下來主要介紹這兩點。

apache kafka的重平衡(rebalance),一直以來都為人詬病。因為重平衡過程會觸發stop-the-world(STW),此時對應topic的資源都會處於不可用的狀態。小規模的叢集還好,如果是大規模的叢集,比如幾百個節點的consumer或kafka connect等,那麼重平衡就是一場災難。所以我們要儘可能避免重平衡,在之前的文章中也有介紹過這點,有關重平衡的基礎內容可以參閱:

詳細解析kafka之 kafka消費者組與重平衡機制

在kafka2.4的時候,社群推出兩個新feature來解決重平衡過程中STW的問題。

  1. Incremental Rebalance Protocol(以下簡稱cooperative協議):改進了eager協議(即舊重平衡協議)的問題,避免STW的發生,具體怎麼避免,後面介紹
  2. static membership:避免重起或暫時離開的消費者觸發重平衡

本篇接下來主要介紹這兩點,另外注意,這兩個功能都是kafka2.4推出的,如果想嚐鮮建議升級到kafka2.4,升級方案參見官網:Upgrading to 2.4.0 from any version 0.8.x through 2.3.x。

apache kafak2.4 incremental cooperative rebalancing協議

背景

負載均衡,基本是分散式系統中必不可少一個功能,apache kafka也不例外。為了讓消費資料這個過程在kafka叢集中儘可能地均衡,kafka推出了重平衡的功能,重平衡能夠幫助kafka客戶端(consumer client,kafka connect,kafka stream)儘可能實現負載均衡。

但是在kafka2.3之前,重平衡各種分配策略基本都是基於eager協議的(包括RangeAssignor,RoundRobinAssignor等,這部分內容最前面給出的文章有介紹),也就是我們以前熟知的kafka重平衡。eager協議重平衡的細節,推薦看極客時間胡夕大佬的文章,講得很詳細,具體的連結就不放了,也可以直接搜kafak重平衡流程解析。

值得一提的是,此前kafka就有推出一個重平衡的新分配策略,StickyAssignor粘性分配策略,主要作用是保證客戶端,比如consumer消費者在重平衡後能夠維持原本的分配方案,可惜的是這個分配策略依舊是在eager協議的框架之下,重平衡仍然需要每個consumer都先放棄當前持有的資源(分割槽)。

在2.x的時候,社群就意識到需要對現有的rebalance作出改變。所以在kafka2.3版本首先在kafka connect應用cooperative協議,然後在kafka2.4的時候也在consumer client添加了該協議的支援。

incremental cooperative rebalancing協議解析

接下來我們介紹cooperative協議和eager協議的具體區別。一句話介紹,cooperative協議將一次全域性重平衡,改成每次小規模重平衡,直至最終收斂平衡的過程

這裡我們主要針對一種場景舉個例子,來對比兩種協議的區別。

假設有這樣一種場景,一個topic有三個分割槽,分別是p1,p2,p3。有兩個消費者c1,c2在消費這三個分割槽,{c1 -> p1, p2},{c2 -> p3}。

當然這樣說不平衡的,所以加入一個消費者c3,此時觸發重平衡。我們先列出在eager協議的框架下會執行的大致步驟,然後再列出cooperative發生的步驟,以做比對。

eager 協議版本
先說下各個名詞:

  • group coordinator:重平衡協調器,負責處理重平衡生命週期中的各種事件
  • hearbeat:consumer和broker的心跳,重平衡時會通過這個心跳通知資訊
  • join group request:consumer客戶端加入組的請求
  • sync group request:重平衡後期,group coordinator向consumer客戶端傳送的分配方案

如果在 eager 版本中,會發生如下事情。

  1. 最開始的時候,c1 c2 各自發送hearbeat心跳資訊給到group coordinator(負責重平衡的協調器)
  2. 這時候group coordinator收到一個join group的request請求,group coordinator知道有新成員加入組了
  3. 在下一個心跳中group coordinator 通知 c1 和 c2 ,準備rebalance
  4. c1 和 c2 放棄(revoke)各自的partition,然後傳送joingroup的request給group coordinator
  5. group coordinator處理好分配方案(交給leader consumer分配的),傳送sync group request給 c1 c2 c3,附帶新的分配方案
  6. c1 c2 c3接收到分配方案後,重新開始消費

用一張圖表示如下:
kafka eager協議重平衡

這裡省略了一些細節,不過整體上應該會更方便理解這個過程。接下來再看看cooperative協議會怎麼處理。

到了cooperative協議就會變成這樣:

cooperative rebalancing protocol 版本

如果在cooperative版本中,會發生如下事情。

  1. 最開始的時候c1 c2各自發送hearbeat心跳資訊給到group co.........