Kafka對于producer發(fā)來的消息怎么保證可靠性碴巾?
每個partition都給配上副本锋勺,做數(shù)據(jù)同步崭添,保證數(shù)據(jù)不丟失。
副本數(shù)據(jù)同步策略
和zookeeper不同的是,Kafka選擇的是全部完成同步郑诺,才發(fā)送ack羡鸥。但是又有所區(qū)別想括。
所以曾沈,你們才會在各種博客看到這句話【kafka不是完全同步这嚣,也不是完全異步,是一種ISR機制】
這句話對也不對塞俱,不對也對(謎語人......)
首先筆者認為:Kafka使用的就是完全同步方案姐帚。
完全同步的優(yōu)點
同樣為了容忍 n 臺節(jié)點的故障,過半機制需要 2n+1 個副本障涯,而全部同步方案只需要 n+1 個副本罐旗,
而 Kafka 的每個分區(qū)都有大量的數(shù)據(jù),過半機制方案會造成大量數(shù)據(jù)的冗余唯蝶。(這就是和zookeeper的不同)
完全同步會有什么問題九秀?
假設就有這么一個follower延遲太高或者某種故障的情況出現(xiàn),導致遲遲不能與leader進行同步粘我。
怎么辦鼓蜒?leader等還是不等?
等吧:producer有話要說:“Kafka也不行啊征字,處理個消息這么費勁都弹,垃圾,你等NM呢等”
不等:那你Kafka對外說完全同步個雞兒匙姜,你這是完全同步么畅厢?
基于此,Kafka的設計者和開發(fā)者想出了一個非常雞賊的點子:ISR
什么是ISR氮昧?
先來看幾個概念
1或详、AR(Assigned Repllicas)一個partition的所有副本(就是replica,不區(qū)分leader或follower)
2郭计、ISR(In-Sync Replicas)能夠和 leader 保持同步的 follower + leader本身 組成的集合霸琴。
3、OSR(Out-Sync Relipcas)不能和 leader 保持同步的 follower 集合
4昭伸、公式:AR = ISR + OSR
所以梧乘,看明白了嗎?
Kafka對外依然可以聲稱是完全同步庐杨,但是承諾是對AR中的所有replica完全同步了嗎选调?
并沒有。Kafka只保證對ISR集合中的所有副本保證完全同步灵份。
至于仁堪,ISR到底有多少個follower,那不知道填渠,別問弦聂,問就是完全同步鸟辅,你再問就多了。
這就好比網(wǎng)購買一送一莺葫,結果郵來了一大一小兩個產(chǎn)品匪凉。
你可能覺得有問題,其實是沒問題的捺檬,商家說送的那個是一模一樣的了嗎再层?并沒有。
ISR就是這個道理堡纬,Kafka是一定會保證leader接收到的消息完全同步給ISR中的所有副本聂受。
而最壞的情況下,ISR中只剩leader自己烤镐。
基于此饺饭,上述完全同步會出現(xiàn)的問題就不是問題了。
因為ISR的機制就保證了职车,處于ISR內部的follower都是可以和leader進行同步的瘫俊,一旦出現(xiàn)故障或延遲,就會被踢出ISR悴灵。
ISR 的核心就是:動態(tài)調整
總結:Kafka采用的就是一種完全同步的方案扛芽,而ISR是基于完全同步的一種優(yōu)化機制。
follower的作用
讀寫都是由leader處理积瞒,follower只是作備份功能川尖,不對外提供服務。
什么情況ISR中的replica會被踢出ISR茫孔?
以前有2個配置
默認10000 即 10秒
replica.lag.time.max.ms
允許 follower 副本落后 leader 副本的消息數(shù)量叮喳,超過這個數(shù)量后,follower 會被踢出 ISR
replica.lag.max.messages
說白了就是一個衡量leader和follower之間差距的標準缰贝。
一個是基于時間間隔馍悟,一個是基于消息條數(shù)。
0.9.0.0版本之后剩晴,移除了replica.lag.max.messages 配置锣咒。
為什么?
因為producer是可以批量發(fā)送消息的赞弥,很容易超過replica.lag.max.messages毅整,那么被踢出ISR的follower就是受了無妄之災。
他們都是沒問題的绽左,既沒有出故障也沒高延遲悼嫉,憑什么被踢?
replica.lag.max.messages調大呢拼窥?調多大戏蔑?太大了是否會有漏網(wǎng)之魚蹋凝,造成數(shù)據(jù)丟失風險?
這就是replica.lag.max.messages的設計缺陷辛臊。
replica.lag.time.max.ms的誤區(qū)
【只要在 replica.lag.time.max.ms 時間內 follower 有同步消息仙粱,即認為該 follower 處于 ISR 中】
你去網(wǎng)上看博客房交,很多博客表達的就是這個意思彻舰,不過筆者認為這么描述很容易誤導初學者。
那我是不是可以理解為候味,follower有個定時任務刃唤,只要在replica.lag.time.max.ms時間內去leader那pull數(shù)據(jù)就行了。
其實不是的白群。千萬不要這么認為尚胞,因為這里還涉及一個速率問題(你理解為蓄水池一個放水一個注水的問題)。
如果leader副本的消息流入速度大于follower副本的拉取速度時帜慢,你follower就是實時同步有什么用笼裳?
典型的出工不出力,消息只會越差越多粱玲,這種follower肯定是要被踢出ISR的躬柬。
當follower副本將leader副本的LEO之前的日志全部同步時,則認為該follower副本已經(jīng)追趕上leader副本抽减。
此時更新該副本的lastCaughtUpTimeMs標識允青。
Kafka的副本管理器(ReplicaManager)啟動時會啟動一個副本過期檢測的定時任務,
會定時檢查當前時間與副本的lastCaughtUpTimeMs差值是否大于參數(shù)replica.lag.time.max.ms指定的值卵沉。
所以replica.lag.time.max.ms的正確理解是:
follower在過去的replica.lag.time.max.ms時間內颠锉,已經(jīng)追趕上leader一次了。
follower到底出了什么問題史汗?
兩個方面琼掠,一個是Kafka自身的問題,另一個是外部原因
Kafka源碼注釋中說明了一般有兩種情況會導致副本失效:
1停撞、follower副本進程卡住眉枕,在一段時間內根本沒有想leader副本發(fā)起同步請求,比如頻繁的Full GC怜森。
2速挑、follower副本進程同步過慢,在一段時間內都無法追趕上leader副本副硅,比如IO開銷過大姥宝。
1、通過工具增加了副本因子恐疲,那么新增加的副本在趕上leader副本之前也都是處于失效狀態(tài)的腊满。
2套么、如果一個follower副本由于某些原因(比如宕機)而下線,之后又上線碳蛋,在追趕上leader副本之前也是出于失效狀態(tài)胚泌。
什么情況OSR中的replica會重新加入ISR?
基于上述肃弟,replica重新追上了leader玷室,就會回到ISR中。
相關的重要概念
需要先明確幾個概念:
1笤受、LEO(last end offset):
當前replica存的最大的offset的下一個值
2穷缤、HW(high watermark):
小于 HW 值的offset所對應的消息被認為是“已提交”或“已備份”的消息,才對消費者可見箩兽。
假設ISR中目前有1個leader津肛,3個follower。
1汗贫、leader接收一個消息身坐,自己保存后,馬上發(fā)送3個請求通知3個follower趕緊保存
2落包、等待3個follower響應保存成功
3部蛇、響應producer,消息提交成功
你是這么想的么妥色?反正當時我是這么想的搪花。
實際上不是的,這個同步是follower主動去請求leader進行同步的嘹害。
因為是每個follower情況不一樣撮竿,所以才會出現(xiàn)LEO和HW的概念。
簡言之笔呀,木桶原理
replica里存了多少數(shù)據(jù)和consumer能消費多少數(shù)據(jù)幢踏,不是一回事。
所謂木桶原理许师,就是把每個replica當作一個木桶的板子房蝉,桶能裝多少水只取決于最短的那塊板子。
這就是也有些人把HW叫成 高水位 的原因微渠。
而 HW 的概念搭幻,也契合前文提到的【完全同步】,HW之前的所有消息逞盆,在ISR中是完全同步的檀蹋。