Kafka 的副本復(fù)制機(jī)制

本文僅為筆者平日學(xué)習(xí)記錄之用睛琳,侵刪
原文:https://mp.weixin.qq.com/s/TUFNictt8XXLmmyWlfnj4g

讓分布式系統(tǒng)的操作變得簡單,在某種程度上是一種藝術(shù)豆村,通常這種實(shí)現(xiàn)都是從大量的實(shí)踐中總結(jié)得到的趾疚。Apache Kafka 的受歡迎程度在很大程度上歸功于其設(shè)計(jì)和操作簡單性奖蔓。隨著社區(qū)添加更多功能,開發(fā)者們會(huì)回過頭來重新思考簡化復(fù)雜行為的方法此迅。

Apache Kafka 中一個(gè)更細(xì)微的功能是它的復(fù)制協(xié)議(replication protocol)汽畴。對(duì)于單個(gè)集群上不同大小的工作負(fù)載,調(diào)整 Kafka replication 以讓它適用不同情況在今天來看是有點(diǎn)棘手的耸序。使這點(diǎn)特別困難的挑戰(zhàn)之一是如何防止副本從同步副本列表(也稱為ISR)加入和退出忍些。從用戶的角度來看,這意味著如果生產(chǎn)者(producer )發(fā)送一批“足夠大”的消息坎怪,那么這可能會(huì)導(dǎo)致 Kafka brokers 發(fā)出多個(gè)警報(bào)罢坝。這些警報(bào)表明某些主題“未被復(fù)制”(under replicated),這意味著數(shù)據(jù)未被復(fù)制到足夠多的 brokers 上搅窿,從而增加數(shù)據(jù)丟失的可能性嘁酿。因此,Kafka cluster 密切監(jiān)控“未復(fù)制的”分區(qū)總數(shù)非常重要男应。在這篇文章中闹司,我將討論導(dǎo)致這種行為的根本原因以及我們?nèi)绾谓鉀Q這個(gè)問題。

一分鐘了解 Kafka 復(fù)制機(jī)制

Kafka 主題中的每個(gè)分區(qū)都有一個(gè)預(yù)寫日志(write-ahead log)沐飘,我們寫入 Kafka 的消息就存儲(chǔ)在這里面游桩。這里面的每條消息都有一個(gè)唯一的偏移量,用于標(biāo)識(shí)它在當(dāng)前分區(qū)日志中的位置耐朴。如下圖所示:

Kafka 中的每個(gè)主題分區(qū)都被復(fù)制了 n 次借卧,其中的 n 是主題的復(fù)制因子(replication factor)。這允許 Kafka 在集群服務(wù)器發(fā)生故障時(shí)自動(dòng)切換到這些副本筛峭,以便在出現(xiàn)故障時(shí)消息仍然可用铐刘。Kafka 的復(fù)制是以分區(qū)為粒度的,分區(qū)的預(yù)寫日志被復(fù)制到 n 個(gè)服務(wù)器影晓。在 n 個(gè)副本中镰吵,一個(gè)副本作為 leader檩禾,其他副本成為 followers。顧名思義捡遍,producer 只能往 leader 分區(qū)上寫數(shù)據(jù)(讀也只能從 leader 分區(qū)上進(jìn)行)锌订,followers 只按順序從 leader 上復(fù)制日志。

日志復(fù)制算法(log replication algorithm)必須提供的基本保證是画株,如果它告訴客戶端消息已被提交,而當(dāng)前 leader 出現(xiàn)故障啦辐,新選出的 leader 也必須具有該消息谓传。在出現(xiàn)故障時(shí),Kafka 會(huì)從掛掉 leader 的 ISR 里面選擇一個(gè) follower 作為這個(gè)分區(qū)新的 leader 芹关;換句話說续挟,是因?yàn)檫@個(gè) follower 是跟上 leader 寫進(jìn)度的。

每個(gè)分區(qū)的 leader 會(huì)維護(hù)一個(gè) in-sync replica(同步副本列表侥衬,又稱 ISR)诗祸。當(dāng) producer 往 broker 發(fā)送消息,消息先寫入到對(duì)應(yīng) leader 分區(qū)上轴总,然后復(fù)制到這個(gè)分區(qū)的所有副本中直颅。只有將消息成功復(fù)制到所有同步副本(ISR)后,這條消息才算被提交怀樟。由于消息復(fù)制延遲受到最慢同步副本的限制功偿,因此快速檢測慢副本并將其從 ISR 中刪除非常重要。Kafka 復(fù)制協(xié)議的細(xì)節(jié)會(huì)有些細(xì)微差別往堡,本博客并不打算對(duì)該主題進(jìn)行詳盡的討論械荷。感興趣的同學(xué)可以到這里詳細(xì)了解 Kafka 復(fù)制的工作原理。

副本在什么情況下才算跟上 leader

一個(gè)副本如果它沒有跟上 leader 的日志進(jìn)度虑灰,那么它可能會(huì)被標(biāo)記為不同步的副本吨瞎。我通過一個(gè)例子來解釋跟上(caught up)的含義。假設(shè)我們有一個(gè)名為 foo 的主題穆咐,并且只有一個(gè)分區(qū)颤诀,同時(shí)復(fù)制因子為 3。假設(shè)此分區(qū)的副本分別在 brokers 1庸娱,2和3上着绊,并且我們已經(jīng)在主題 foo 上提交了3條消息。brokers 1上的副本是 leader熟尉,副本2和3是 followers归露,所有副本都是 ISR 的一部分。假設(shè) replica.lag.max.messages 設(shè)置為4斤儿,這意味著只要 follower 落后 leader 的消息不超過3條剧包,它就不會(huì)從 ISR 中刪除恐锦。我們把 replica.lag.time.max.ms 設(shè)置為500毫秒,這意味著只要 follower 每隔500毫秒或更早地向 leader 發(fā)送一個(gè) fetch 請(qǐng)求疆液,它們就不會(huì)被標(biāo)記為死亡并且不會(huì)從 ISR 中刪除一铅。

現(xiàn)在假設(shè) producer 往 leader 上發(fā)送下一條消息,與此同時(shí)堕油,broker 3 上發(fā)生了 GC 停頓潘飘,現(xiàn)在每個(gè) broker 上的分區(qū)情況如下所示:

由于 broker 3 在 ISR中,因此在將 broker 3從 ISR 中移除或 broker 3 上的分區(qū)跟上 leader 的日志結(jié)束偏移之前掉缺,最新消息都是不認(rèn)為被提交的卜录。注意,由于 border 3 落后 leader 的消息比 replica.lag.max.messages = 4 要小眶明,因此不符合從 ISR 中刪除的條件艰毒。這意味著 broker 3 上的分區(qū)需要從 leader 上同步 offset 為 3 的消息,如果它做到了搜囱,那么這個(gè)副本就是跟上 leader 的丑瞧。假設(shè) broker 3 在 100ms 內(nèi) GC 完成了,并且跟上了 leader 的日志結(jié)束偏移蜀肘,那么最新的情況如下圖:

image

什么情況下會(huì)導(dǎo)致一個(gè)副本與 leader 失去同步

一個(gè)副本與 leader 失去同步的原因有很多绊汹,主要包括:

  • 慢副本(Slow replica):follower replica 在一段時(shí)間內(nèi)一直無法趕上 leader 的寫進(jìn)度。造成這種情況的最常見原因之一是 follower replica 上的 I/O瓶頸幌缝,導(dǎo)致它持久化日志的時(shí)間比它從 leader 消費(fèi)消息的時(shí)間要長灸促;

  • 卡住副本(Stuck replica):follower replica 在很長一段時(shí)間內(nèi)停止從 leader 獲取消息。這可能是以為 GC 停頓涵卵,或者副本出現(xiàn)故障浴栽;

  • 剛啟動(dòng)副本(Bootstrapping replica):當(dāng)用戶給某個(gè)主題增加副本因子時(shí),新的 follower replicas 是不同步的轿偎,直到它跟上 leader 的日志典鸡。

當(dāng)副本落后于 leader 分區(qū)時(shí),這個(gè)副本被認(rèn)為是不同步或滯后的坏晦。在 Kafka 0.8.2 中萝玷,副本的滯后于 leader 是根據(jù) replica.lag.max.messages 或 replica.lag.time.max.ms 來衡量的;前者用于檢測慢副本(Slow replica)昆婿,而后者用于檢測卡住副本(Stuck replica)球碉。

如何確認(rèn)某個(gè)副本處于滯后狀態(tài)

通過 replica.lag.time.max.ms 來檢測卡住副本(Stuck replica)在所有情況下都能很好地工作。它跟蹤 follower 副本沒有向 leader 發(fā)送獲取請(qǐng)求的時(shí)間仓蛆,通過這個(gè)可以推斷 follower 是否正常睁冬。另一方面,使用消息數(shù)量檢測不同步慢副本(Slow replica)的模型只有在為單個(gè)主題或具有同類流量模式的多個(gè)主題設(shè)置這些參數(shù)時(shí)才能很好地工作看疙,但我們發(fā)現(xiàn)它不能擴(kuò)展到生產(chǎn)集群中所有主題豆拨。在我之前的示例的基礎(chǔ)上直奋,如果主題 foo 以 2 msg/sec 的速率寫入數(shù)據(jù),其中 leader 收到的單個(gè)批次通常永遠(yuǎn)不會(huì)超過3條消息施禾,那么我們知道這個(gè)主題的 replica.lag.max.messages 參數(shù)可以設(shè)置為 4脚线。為什么?因?yàn)槲覀円宰畲笏俣韧?leader 寫數(shù)據(jù)并且在 follower 副本復(fù)制這些消息之前弥搞,follower 的日志落后于 leader 不超過3條消息邮绿。同時(shí),如果主題 foo 的 follower 副本始終落后于 leader 超過3條消息拓巧,則我們希望 leader 刪除慢速 follower 副本以防止消息寫入延遲增加斯碌。

這本質(zhì)上是 replica.lag.max.messages 的目標(biāo) - 能夠檢測始終與 leader 不同步的副本。假設(shè)現(xiàn)在這個(gè)主題的流量由于峰值而增加肛度,生產(chǎn)者最終往 foo 發(fā)送了一批包含4條消息,等于 replica.lag.max.messages = 4 的配置值投慈。此時(shí)承耿,兩個(gè) follower 副本將被視為與 leader 不同步,并被移除 ISR伪煤。

但是加袋,由于兩個(gè) follower 副本都處于活動(dòng)狀態(tài),因此它們將在下一個(gè) fetch 請(qǐng)求中趕上 leader 的日志結(jié)束偏移量并被添加回 ISR抱既。如果生產(chǎn)者繼續(xù)向 leader 發(fā)送大量的消息职烧,則將重復(fù)上述相同的過程。這證明了 follower 副本進(jìn)出 ISR 時(shí)觸發(fā)不必要的錯(cuò)誤警報(bào)的情況防泵。

replica.lag.max.messages 參數(shù)的核心問題是蚀之,用戶必須猜測如何配置這個(gè)值,因?yàn)槲覀儾恢?Kafka 的傳入流量到底會(huì)到多少捷泞,特別是在網(wǎng)絡(luò)峰值的情況下足删。

一個(gè)參數(shù)搞定一切

我們意識(shí)到,檢測卡住或慢速副本真正重要的事情锁右,是副本與 leader 不同步的時(shí)間失受。我們刪除了通過猜測來設(shè)置的 replica.lag.max.messages 參數(shù)。現(xiàn)在咏瑟,我們只需要在服務(wù)器上配置 replica.lag.time.max.ms 參數(shù)即可拂到;這個(gè)參數(shù)的含義為副本與 leader 不同步的時(shí)間。

檢測卡住副本(Stuck replica)的方式與以前相同 - 如果副本未能在 replica.lag.time.max.ms 時(shí)間內(nèi)發(fā)送 fetch 請(qǐng)求码泞,則會(huì)將其視為已死的副本并從 ISR 中刪除兄旬;

檢測慢副本的機(jī)制已經(jīng)改變 - 如果副本落后于 leader 的時(shí)間超過 replica.lag.time.max.ms,則認(rèn)為它太慢并且從 ISR 中刪除浦夷。

因此辖试,即使在峰值流量下辜王,生產(chǎn)者往 leader 發(fā)送大量的消息,除非副本始終和 leader 保持 replica.lag.time.max.ms 時(shí)間的落后罐孝,否則它不會(huì)隨機(jī)進(jìn)出 ISR呐馆。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市莲兢,隨后出現(xiàn)的幾起案子汹来,更是在濱河造成了極大的恐慌,老刑警劉巖改艇,帶你破解...
    沈念sama閱讀 219,039評(píng)論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件收班,死亡現(xiàn)場離奇詭異,居然都是意外死亡谒兄,警方通過查閱死者的電腦和手機(jī)摔桦,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,426評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來承疲,“玉大人邻耕,你說我怎么就攤上這事⊙喔耄” “怎么了兄世?”我有些...
    開封第一講書人閱讀 165,417評(píng)論 0 356
  • 文/不壞的土叔 我叫張陵,是天一觀的道長啊研。 經(jīng)常有香客問我御滩,道長,這世上最難降的妖魔是什么党远? 我笑而不...
    開封第一講書人閱讀 58,868評(píng)論 1 295
  • 正文 為了忘掉前任削解,我火速辦了婚禮,結(jié)果婚禮上麸锉,老公的妹妹穿的比我還像新娘钠绍。我一直安慰自己,他們只是感情好花沉,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,892評(píng)論 6 392
  • 文/花漫 我一把揭開白布柳爽。 她就那樣靜靜地躺著,像睡著了一般碱屁。 火紅的嫁衣襯著肌膚如雪磷脯。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,692評(píng)論 1 305
  • 那天娩脾,我揣著相機(jī)與錄音赵誓,去河邊找鬼。 笑死,一個(gè)胖子當(dāng)著我的面吹牛俩功,可吹牛的內(nèi)容都是我干的幻枉。 我是一名探鬼主播,決...
    沈念sama閱讀 40,416評(píng)論 3 419
  • 文/蒼蘭香墨 我猛地睜開眼诡蜓,長吁一口氣:“原來是場噩夢(mèng)啊……” “哼熬甫!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起蔓罚,我...
    開封第一講書人閱讀 39,326評(píng)論 0 276
  • 序言:老撾萬榮一對(duì)情侶失蹤椿肩,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后豺谈,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體郑象,經(jīng)...
    沈念sama閱讀 45,782評(píng)論 1 316
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,957評(píng)論 3 337
  • 正文 我和宋清朗相戀三年茬末,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了厂榛。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 40,102評(píng)論 1 350
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡丽惭,死狀恐怖噪沙,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情吐根,我是刑警寧澤,帶...
    沈念sama閱讀 35,790評(píng)論 5 346
  • 正文 年R本政府宣布辐马,位于F島的核電站拷橘,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏喜爷。R本人自食惡果不足惜冗疮,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,442評(píng)論 3 331
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望檩帐。 院中可真熱鬧术幔,春花似錦、人聲如沸湃密。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,996評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽泛源。三九已至拔妥,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間达箍,已是汗流浹背没龙。 一陣腳步聲響...
    開封第一講書人閱讀 33,113評(píng)論 1 272
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人硬纤。 一個(gè)月前我還...
    沈念sama閱讀 48,332評(píng)論 3 373
  • 正文 我出身青樓解滓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親筝家。 傳聞我的和親對(duì)象是個(gè)殘疾皇子洼裤,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,044評(píng)論 2 355