聊聊 Kafka: Consumer 源碼解析之 Rebalance 機(jī)制

一赊舶、前言

我們上一篇分析了 Consumer 如何加入 Consumer Group渠羞,其實(shí)上一篇是一個(gè)很宏觀的東西票从,主要講 ConsumerCoordinator 怎么與 GroupCoordinator 通信暮现。等等嘹承,老周,ConsumerCoordinator 和 GroupCoordinator 是個(gè)啥玩意捌刮?這兩個(gè)組件分別是 Consumer碰煌、Kafka Broker 的協(xié)調(diào)器,說(shuō)白了就是我們?cè)O(shè)計(jì)模式中的門(mén)面模式绅作,具體的內(nèi)容可以看上一篇回顧下芦圾。今天這一篇主要講上一篇 Consumer 如何加入 Consumer Group 中的 Rebalance 機(jī)制,其實(shí)上一篇講了大概了俄认,這一篇更深入的來(lái)說(shuō)一說(shuō) Rebalance 機(jī)制的具體細(xì)節(jié)个少。

如果你是一個(gè)有一定經(jīng)驗(yàn)的程序員,Rebalance 機(jī)制我覺(jué)得可以作為一道面試題來(lái)考察眯杏,而且還是有一定難度的夜焦。但是也不需要妄自菲薄,跟著老周的這篇文章下來(lái)岂贩,相信你一定可以拿下它的茫经。

但有些讀者確實(shí)覺(jué)得還是有一定難度,別著急萎津,先看下下面 Kafka 的拓?fù)浣Y(jié)構(gòu)卸伞,這個(gè)結(jié)構(gòu)很清晰了吧,如果你對(duì) Kafka 的拓?fù)浣Y(jié)構(gòu)還不了解锉屈,那我建議你先別往下看了荤傲,先把 Kafka 的拓?fù)浣Y(jié)構(gòu)搞清楚,或者先看老周前面的幾篇文章再來(lái)繼續(xù)閱讀颈渊,我覺(jué)得效果會(huì)更好遂黍。


在這里插入圖片描述

這一篇主要從以下幾點(diǎn)來(lái)聊一聊 Rebalance 機(jī)制:

  • 什么是 Rebalance 機(jī)制终佛?
  • 觸發(fā) Rebalance 機(jī)制的時(shí)機(jī)
  • Group 狀態(tài)變更
  • 舊版消費(fèi)者客戶端的問(wèn)題
  • Rebalance 機(jī)制的原理
  • Broker 端重平衡場(chǎng)景

二、什么是 Rebalance 機(jī)制妓湘?

Rebalance 本質(zhì)上是一種協(xié)議查蓉,規(guī)定了一個(gè) Consumer Group 下的所有 Consumer 如何達(dá)成一致,來(lái)分配訂閱 Topic 的每個(gè)分區(qū)榜贴。

當(dāng)集群中有新成員加入,或者某些主題增加了分區(qū)之后妹田,消費(fèi)者是怎么進(jìn)行重新分配消費(fèi)的唬党?這里就涉及到重平衡(Rebalance)的概念,下面我就給大家講解一下什么是 Kafka 重平衡機(jī)制鬼佣。


在這里插入圖片描述

從圖中可以找到消費(fèi)組模型的幾個(gè)概念:

  • 同一個(gè)消費(fèi)組驶拱,一個(gè)分區(qū)只能被一個(gè)消費(fèi)者訂閱消費(fèi),但一個(gè)消費(fèi)者可訂閱多個(gè)分區(qū)晶衷,也就是說(shuō)每條消息只會(huì)被同一個(gè)消費(fèi)組的某一個(gè)消費(fèi)者消費(fèi)蓝纲,確保不會(huì)被重復(fù)消費(fèi);
  • 一個(gè)分區(qū)可被不同消費(fèi)組訂閱晌纫,這里有種特殊情況税迷,假如每個(gè)消費(fèi)組只有一個(gè)消費(fèi)者,這樣分區(qū)就會(huì)廣播到所有消費(fèi)者上锹漱,實(shí)現(xiàn)廣播模式消費(fèi)箭养。

要想實(shí)現(xiàn)以上消費(fèi)組模型,那么就要實(shí)現(xiàn)當(dāng)外部環(huán)境變化時(shí)哥牍,比如主題新增了分區(qū)毕泌,消費(fèi)組有新成員加入等情況,實(shí)現(xiàn)動(dòng)態(tài)調(diào)整以維持以上模型嗅辣,那么這個(gè)工作就會(huì)交給 Kafka 重平衡(Rebalance)機(jī)制去處理撼泛。

在這里插入圖片描述

從圖中可看出,Kafka 重平衡是外部觸發(fā)導(dǎo)致的澡谭,下面來(lái)看下觸發(fā) Kafka 重平衡的時(shí)機(jī)有哪些愿题。

三、觸發(fā) Rebalance 機(jī)制的時(shí)機(jī)

  • 有新的 Consumer 加入 Consumer Group
  • 有 Consumer 宕機(jī)下線译暂。Consumer 并不一定需要真正下線抠忘,例如遇到長(zhǎng)時(shí)間的 GC、網(wǎng)絡(luò)延遲導(dǎo)致消費(fèi)者長(zhǎng)時(shí)間未向 GroupCoordinator 發(fā)送 HeartbeatRequest 時(shí)外永,GroupCoordinator 會(huì)認(rèn)為 Consumer 下線崎脉。
  • 有 Consumer 主動(dòng)退出 Consumer Group(發(fā)送 LeaveGroupRequest 請(qǐng)求)。比如客戶端調(diào)用了 unsubscribe() 方法取消對(duì)某些主題的訂閱伯顶。
  • Consumer 消費(fèi)超時(shí)囚灼,沒(méi)有在指定時(shí)間內(nèi)提交 offset 偏移量骆膝。
  • Consumer Group 所對(duì)應(yīng)的 GroupCoordinator 節(jié)點(diǎn)發(fā)生了變更。
  • Consumer Group 所訂閱的任一主題或者主題的分區(qū)數(shù)量發(fā)生變化灶体。

四阅签、Group 狀態(tài)變更

4.1 消費(fèi)端

在 Consumer 側(cè)的門(mén)面 ConsumerCoordinator,它繼承了 AbstractCoordinator 抽象類蝎抽。在協(xié)調(diào)器 AbstractCoordinator 中的內(nèi)部類 MemberState 中我們可以看到協(xié)調(diào)器的四種狀態(tài)政钟,分別是未注冊(cè)、重分配后沒(méi)收到響應(yīng)樟结、重分配后收到響應(yīng)但還沒(méi)有收到分配养交、穩(wěn)定狀態(tài)。


在這里插入圖片描述

上述消費(fèi)端的四種狀態(tài)的轉(zhuǎn)換如下圖所示:


在這里插入圖片描述

4.2 服務(wù)端

對(duì)于 Kafka 服務(wù)端的 GroupCoordinator 則有五種狀態(tài) Empty瓢宦、PreparingRebalance碎连、CompletingRebalance、Stable驮履、Dead鱼辙。他們的狀態(tài)轉(zhuǎn)換如下圖所示:

在這里插入圖片描述
狀態(tài) 含義
Empty 組內(nèi)沒(méi)有任何成員,但消費(fèi)者組可能存在已提交的位移數(shù)據(jù)玫镐,而且這些位移數(shù)據(jù)尚未過(guò)期倒戏。
Dead 同樣是組內(nèi)沒(méi)有任何成員,但組的元數(shù)據(jù)信息已經(jīng)在協(xié)調(diào)者端被移除摘悴。協(xié)調(diào)者組件保存著向它注冊(cè)過(guò)的所有組信息峭梳,所謂的元數(shù)據(jù)信息就類似這個(gè)注冊(cè)信息。
PreparingRebalance 消費(fèi)者組準(zhǔn)備開(kāi)啟重平衡蹂喻,此時(shí)所有成員都要重新請(qǐng)求加入消費(fèi)者組葱椭。
CompletingRebalance 消費(fèi)者組下所有成員已經(jīng)加入,各個(gè)成員正在等待分配方案口四。該狀態(tài)在老一點(diǎn)的版本中稱為 AwaitingSync孵运,它和 CompletingRebalance 是等價(jià)的。
Stable 消費(fèi)組的穩(wěn)定狀態(tài)蔓彩。該狀態(tài)表明重平衡已經(jīng)完成治笨,組內(nèi)各成員能夠正常消費(fèi)數(shù)據(jù)了。
在這里插入圖片描述
  • 一個(gè)消費(fèi)者組最開(kāi)始是 Empty
  • 重平衡開(kāi)啟后赤嚼,會(huì)置于 PreparingRebalance 等待成員加入旷赖。
  • 之后變更到 CompletingRebalance 等待分配方案
  • 最后流轉(zhuǎn)到 Stable 完成 Rebalance
  • 當(dāng)有成員變動(dòng)時(shí),消費(fèi)者組狀態(tài)從 Stable 變?yōu)?PreparingRebalance更卒。
    • 此時(shí)所有現(xiàn)存成員需要重新申請(qǐng)加入組
    • 當(dāng)所有組成員都退出組后等孵,消費(fèi)者組狀態(tài)為 Empty。
  • 消費(fèi)者組處于 Empty 狀態(tài)蹂空,Kafka 會(huì)定期自動(dòng)刪除過(guò)期 offset俯萌。

五果录、舊版消費(fèi)者客戶端的問(wèn)題

ConsumerCoordinator 與 GroupCoordinator 的概念是針對(duì) Kafka 0.9.0 版本后的消費(fèi)者客戶端而言的,我們 暫且把 Kafka 0.9.0 版本之前的消費(fèi)者客戶端稱為舊版消費(fèi)者客戶端咐熙。舊版消費(fèi)者客戶端是使用 Zookeeper 的監(jiān)聽(tīng)器(Watcher)來(lái)實(shí)現(xiàn)這些功能的弱恒。

每個(gè)消費(fèi)組 <group> 在 Zookeeper 中維護(hù)了一個(gè) /consumers/<group>/ids 路徑,在此路徑下使用臨時(shí)節(jié)點(diǎn)記錄隸屬于此消費(fèi)組的消費(fèi)者的唯一標(biāo)識(shí) consumerldString , consumerldString 由消費(fèi)者啟動(dòng)時(shí)創(chuàng)建棋恼。消費(fèi)者的唯一標(biāo)識(shí)由 consumer.id+主機(jī)名+時(shí)間戳+UUID的部分信息 構(gòu)成返弹,其中 consumer.id 是舊版消費(fèi)者客戶端中的配置,相當(dāng)于新版客戶端中的 client.id蘸泻。比如某個(gè)消費(fèi)者的唯一標(biāo)識(shí)為 consumerld_localhost-1510734527562-64b377f5琉苇,那么其中 consumerld 為指定的 consumer.id, localhost 為計(jì)算機(jī)的主機(jī)名,1510734527562代表時(shí)間戳悦施,而 64b377f5 表示 UUID 的部分信息。

下圖與 /consumers/<group>/ids 同級(jí)的還有兩個(gè)節(jié)點(diǎn):ownersoffsets

  • /consumers/<group>/owners 路徑下記錄了分區(qū)和消費(fèi)者的對(duì)應(yīng)關(guān)系
  • /consumers/<group>/offsets 路徑下記錄了此消費(fèi)組在分區(qū)中對(duì)應(yīng)的消費(fèi)位移
在這里插入圖片描述

每個(gè) broker去团、主題和分區(qū)在 Zookeeper 中也都對(duì)應(yīng)一個(gè)路徑:

  • /brokers/ids/<id>記錄了 host抡诞、port 及分配在此 broker 上的主題分區(qū)列表;
  • /brokers/topics/<topic> 記錄了每個(gè)分區(qū)的 leader 副本土陪、ISR 集合等信息昼汗。
  • /brokers/topics/<topic>/partitions/<partition>/state 記錄了當(dāng)前 leader 副本、leader epoch 等信息鬼雀。

每個(gè)消費(fèi)者在啟動(dòng)時(shí)都會(huì)在 /consumers/<group>/ids/brokers/ids 路徑上注冊(cè)一個(gè)監(jiān)聽(tīng)器顷窒。當(dāng) /consumers/<group>/ids 路徑下的子節(jié)點(diǎn)發(fā)生變化時(shí),表示消費(fèi)組中的消 費(fèi)者發(fā)生了變化源哩;當(dāng) /brokers/ids 路徑下的子節(jié)點(diǎn)發(fā)生變化時(shí)鞋吉,表示 broker 出現(xiàn)了增減。這樣通過(guò) Zookeeper 所提供的 Watcher励烦,每個(gè)消費(fèi)者就可以監(jiān)聽(tīng)消費(fèi)組和 Kafka 集群的狀態(tài)了谓着。

這種方式下每個(gè)消費(fèi)者對(duì) Zookeeper 的相關(guān)路徑分別進(jìn)行監(jiān)聽(tīng),當(dāng)觸發(fā)再均衡操作時(shí)坛掠,一個(gè)消費(fèi)組下的所有消費(fèi)者會(huì)同時(shí)進(jìn)行再均衡操作赊锚,而消費(fèi)者之間并不知道彼此操作的結(jié)果,這樣可能導(dǎo)致 Kafka 工作在一個(gè)不正確的狀態(tài)屉栓。與此同時(shí)舷蒲,這種嚴(yán)重依賴于 Zookeeper 集群的做法還有兩個(gè)比較嚴(yán)重的問(wèn)題。

  • 羊群效應(yīng)(Herd Effect):所謂的羊群效應(yīng)是指 Zookeeper 中一個(gè)被監(jiān)聽(tīng)的節(jié)點(diǎn)變化友多,大量的 Watcher 通知被發(fā)送到客戶端牲平,導(dǎo)致在通知期間的其他操作延遲,也有可能發(fā)生類似死鎖的情況夷陋。
  • 腦裂問(wèn)題(Split Brain):消費(fèi)者進(jìn)行再均衡操作時(shí)每個(gè)消費(fèi)者都與 Zookeeper 進(jìn)行通信以判斷消費(fèi)者或 broker 變化的情況欠拾,由于 Zookeeper 本身的特性胰锌,可能導(dǎo)致在同一時(shí)刻各個(gè)消費(fèi)者獲取的狀態(tài)不一致,這樣會(huì)導(dǎo)致異常問(wèn)題發(fā)生藐窄。

六资昧、Rebalance 機(jī)制的原理

Kafka 0.9.0 版本后的消費(fèi)者客戶端對(duì)此進(jìn)行了重新設(shè)計(jì),將全部消費(fèi)組分成多個(gè)子集荆忍,每個(gè)消費(fèi)組的
子集在服務(wù)端對(duì)應(yīng)一個(gè) GroupCoordinator 對(duì)其進(jìn)行管理格带,GroupCoordinator 是 Kafka 服務(wù)端中用于管理消費(fèi)組的組件。而消費(fèi)者客戶端中的 ConsumerCoordinator 組件負(fù)責(zé)與 GroupCoordinator 進(jìn)行交互刹枉。

  • Rebalance 完整流程需要 Consumer & Coordinator 共同完成
  • Consumer 端 Rebalance 步驟
    • 加入組:對(duì)應(yīng) JoinGroup 請(qǐng)求
    • 等待 Leader Consumer 分配方案:對(duì)應(yīng) SyncGroup 請(qǐng)求
  • 當(dāng)組內(nèi)成員加入組時(shí)叽唱,Consumer 向協(xié)調(diào)者發(fā)送 JoinGroup 請(qǐng)求。
  • 每個(gè) Consumer 會(huì)上報(bào)自己訂閱的 topic
  • Coordinator 收集到所有 JoinGroup 請(qǐng)求后微宝,從這些成員中選擇一個(gè)擔(dān)任消費(fèi)者組的 Leader
    • 通常第一個(gè)發(fā)送 JoinGroup 請(qǐng)求的自動(dòng)成為 Leader
  • Leader Consumer 的任務(wù)是收集所有成員的 topic棺亭,根據(jù)信息制定具體的 partition consumer 分配方案。
  • 選出 Leader 后蟋软,協(xié)調(diào)者把所有 topic 信息封裝到 JoinGroup Response 中镶摘,發(fā)送給 Leader。
  • Leader Consumer 做出統(tǒng)一分配方案岳守,進(jìn)入到 SyncGroup 請(qǐng)求凄敢。
  • Leader Consumer 向協(xié)調(diào)者發(fā)送 SyncGroup,將分配方案發(fā)給協(xié)調(diào)者湿痢。
  • 其他成員也會(huì)發(fā)出 SyncGroup 請(qǐng)求
  • 協(xié)調(diào)者以 SyncGroup Response 的方式將方案下發(fā)給所有成員


    在這里插入圖片描述

    在這里插入圖片描述
  • 所有成員成功接收到分配方案涝缝,消費(fèi)者組進(jìn)入 Stable 狀態(tài),開(kāi)始正常消費(fèi)譬重。

具體的源碼分析拒逮,可以看我上一篇分析的 Consumer 如何加入 Consumer Group 文章。

七害幅、Broker 端重平衡場(chǎng)景

7.1 新成員加入

  • 消費(fèi)者組處于 Stable 之后有新成員加入
在這里插入圖片描述

7.2 組成員主動(dòng)離開(kāi)

  • 主動(dòng)離開(kāi):Consumer Instance 通過(guò)調(diào)用 close() 方法通知協(xié)調(diào)者退出
  • 該場(chǎng)景涉及第三個(gè)請(qǐng)求:LeaveGroup 請(qǐng)求
在這里插入圖片描述

7.3 組成員崩潰離開(kāi)

  • 協(xié)調(diào)者需要等待一段時(shí)間才能感知
  • 這個(gè)時(shí)間段由 Consumer 端參數(shù) sessionn.timeout.ms 控制
  • Kafka 不會(huì)超過(guò)上述參數(shù)時(shí)間感知崩潰
  • 處理流程相同
在這里插入圖片描述

7.4 Rebalance 時(shí)組成員提交 offset

  • Rebalance 開(kāi)啟時(shí)消恍,協(xié)調(diào)者會(huì)給予成員一段緩沖時(shí)間,要求每個(gè)成員在這段時(shí)間內(nèi)快速上報(bào)自己的 offset以现。
  • 再開(kāi)啟正常的 JoinGroup/SyncGroup 請(qǐng)求
在這里插入圖片描述

好了狠怨,Rebalance 機(jī)制就先說(shuō)這么多了,下一篇會(huì)來(lái)聊一聊如何避免重平衡邑遏。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末佣赖,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子记盒,更是在濱河造成了極大的恐慌憎蛤,老刑警劉巖,帶你破解...
    沈念sama閱讀 206,311評(píng)論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異俩檬,居然都是意外死亡萎胰,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,339評(píng)論 2 382
  • 文/潘曉璐 我一進(jìn)店門(mén)棚辽,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)技竟,“玉大人,你說(shuō)我怎么就攤上這事屈藐±谱椋” “怎么了?”我有些...
    開(kāi)封第一講書(shū)人閱讀 152,671評(píng)論 0 342
  • 文/不壞的土叔 我叫張陵联逻,是天一觀的道長(zhǎng)搓扯。 經(jīng)常有香客問(wèn)我,道長(zhǎng)包归,這世上最難降的妖魔是什么锨推? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 55,252評(píng)論 1 279
  • 正文 為了忘掉前任,我火速辦了婚禮公壤,結(jié)果婚禮上爱态,老公的妹妹穿的比我還像新娘。我一直安慰自己境钟,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,253評(píng)論 5 371
  • 文/花漫 我一把揭開(kāi)白布俭识。 她就那樣靜靜地躺著慨削,像睡著了一般。 火紅的嫁衣襯著肌膚如雪套媚。 梳的紋絲不亂的頭發(fā)上缚态,一...
    開(kāi)封第一講書(shū)人閱讀 49,031評(píng)論 1 285
  • 那天,我揣著相機(jī)與錄音堤瘤,去河邊找鬼玫芦。 笑死,一個(gè)胖子當(dāng)著我的面吹牛本辐,可吹牛的內(nèi)容都是我干的桥帆。 我是一名探鬼主播,決...
    沈念sama閱讀 38,340評(píng)論 3 399
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼慎皱,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼老虫!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起茫多,我...
    開(kāi)封第一講書(shū)人閱讀 36,973評(píng)論 0 259
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤祈匙,失蹤者是張志新(化名)和其女友劉穎,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體夺欲,經(jīng)...
    沈念sama閱讀 43,466評(píng)論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡跪帝,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 35,937評(píng)論 2 323
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了些阅。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片伞剑。...
    茶點(diǎn)故事閱讀 38,039評(píng)論 1 333
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖扑眉,靈堂內(nèi)的尸體忽然破棺而出纸泄,到底是詐尸還是另有隱情,我是刑警寧澤腰素,帶...
    沈念sama閱讀 33,701評(píng)論 4 323
  • 正文 年R本政府宣布聘裁,位于F島的核電站,受9級(jí)特大地震影響弓千,放射性物質(zhì)發(fā)生泄漏衡便。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,254評(píng)論 3 307
  • 文/蒙蒙 一洋访、第九天 我趴在偏房一處隱蔽的房頂上張望镣陕。 院中可真熱鬧,春花似錦姻政、人聲如沸呆抑。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 30,259評(píng)論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)鹊碍。三九已至,卻和暖如春食绿,著一層夾襖步出監(jiān)牢的瞬間侈咕,已是汗流浹背。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 31,485評(píng)論 1 262
  • 我被黑心中介騙來(lái)泰國(guó)打工器紧, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留耀销,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 45,497評(píng)論 2 354
  • 正文 我出身青樓铲汪,卻偏偏與公主長(zhǎng)得像熊尉,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子桥状,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,786評(píng)論 2 345

推薦閱讀更多精彩內(nèi)容