Kafka的副本機(jī)制
- 副本,簡單來說就是另一個(gè)存儲(chǔ)文件谷誓,比如mysql的只讀庫就可以看成一個(gè)副本掸绞,一般使用副本主要有三個(gè)方面的優(yōu)勢(shì)
- 能夠提供數(shù)據(jù)的冗余淹遵,在宕機(jī)或者磁盤損壞的時(shí)候继找,及時(shí)恢復(fù)數(shù)據(jù)
- 能夠提供橫向的擴(kuò)展遂跟,通過增加機(jī)器(類似于mysql的只讀庫)來提高讀操作的吞吐量
- 改善數(shù)據(jù)的局部性,比如cdn的節(jié)點(diǎn)數(shù)據(jù),將數(shù)據(jù)落到用戶最近的節(jié)點(diǎn)上
- 但是kafka的副本的作用只是數(shù)據(jù)冗余的功能幻锁,其他的兩個(gè)功能沒有體現(xiàn)出來
- kafka 副本可以是一個(gè)分區(qū)下按照不同的topic進(jìn)行副本的創(chuàng)建凯亮,但是副本只是進(jìn)行異步的拉取同步數(shù)據(jù),不對(duì)外提供數(shù)據(jù)哄尔,因此將副本分成領(lǐng)導(dǎo)副本和追隨者副本假消,只有在領(lǐng)導(dǎo)副本掛掉滯后,會(huì)在追隨者副本中選取領(lǐng)導(dǎo)副本岭接,對(duì)外提供服務(wù)置谦;
- 關(guān)于追隨者副本不對(duì)外提供數(shù)據(jù)的情況,能夠提供穩(wěn)定的對(duì)外數(shù)據(jù)亿傅,所寫即所得,不會(huì)因?yàn)樽x取了不同副本的數(shù)據(jù)瘟栖,副本之間數(shù)據(jù)不統(tǒng)一導(dǎo)致結(jié)果不一致葵擎;
- 關(guān)于追隨者副本是否和leader 副本保持一致的界限,并不是說必須是消息一致才能是一致半哟,而是允許在一個(gè)同步間隙內(nèi)的誤差酬滤,用 replica.lag.time.max.ms來控制,比如設(shè)置的是10秒寓涨,kafka允許在追隨者副本的消息落后leader副本的時(shí)間在10秒之內(nèi)
- In-sync Replicas (ISR) 是記錄與leader副本一致的副本集合盯串,是一個(gè)動(dòng)態(tài)的集合,因?yàn)樽冯S者副本是通過異步拉取數(shù)據(jù)的戒良,因此在某些情況下可能會(huì)不同步体捏,而且落后時(shí)間較長,此時(shí)isr
記錄中會(huì)將這個(gè)副本移除糯崎,在此之后如果副本同步到了一致性的要求的時(shí)候几缭,會(huì)重新放到isr中 - ISR 不只是追隨者副本集合,它必然包括 Leader 副本沃呢。甚至在某些情況下年栓,ISR 只有 Leader 這一個(gè)副本
- 在leader副本掛掉的時(shí)候,isr集合中可能為空薄霜,此時(shí)如何選取leader呢某抓,需要看參數(shù)設(shè)置情況,一般說來惰瓜,如果配置了unclean.leader.election.enable 的話否副,kafka會(huì)在那些不同步的副本中選取副本作為leader副本,以便提供高可用的服務(wù)鸵熟,但是由于這些副本落后很多數(shù)據(jù)副编,可能會(huì)造成其他業(yè)務(wù)上的問題,因此一般該參數(shù)設(shè)置為false,來保證數(shù)據(jù)的一致性痹届;(在高可用和數(shù)據(jù)一致性的選擇上呻待,傾向于選擇一致性,因?yàn)楦呖捎玫脑捒梢酝ㄟ^其他措施來彌補(bǔ))
Kafka 是如何處理請(qǐng)求的
- Kafka作為一個(gè)高性能的讀寫消息引擎队腐,所有的連接都是tcp的socket連接蚕捉,為了提高吞吐量使用了Reactor 模型來處理整個(gè)請(qǐng)求和響應(yīng),在kafka中將請(qǐng)求分為兩大類柴淘,數(shù)據(jù)請(qǐng)求和控制類請(qǐng)求迫淹,其中控制類請(qǐng)求的優(yōu)先級(jí)高于數(shù)據(jù)類請(qǐng)求,控制類請(qǐng)求可以使數(shù)據(jù)類請(qǐng)求立即失敗为严。
-
kafka中數(shù)據(jù)類請(qǐng)求的請(qǐng)求模型
請(qǐng)求模型 - 請(qǐng)求進(jìn)來之后敛熬,首先會(huì)進(jìn)入到網(wǎng)絡(luò)線程池中,這一部分就是使用reactor模型處理的第股,但是并不是直接響應(yīng)应民,而是將數(shù)據(jù)放到共享隊(duì)列中,使用一個(gè)io線程池去異步的處理共享隊(duì)列中的請(qǐng)求(將數(shù)據(jù)放到可以提高整個(gè)數(shù)據(jù)的吞吐量夕吻,如果不放到共享隊(duì)列中的話诲锹,大部分讀寫請(qǐng)求是需要直接處理的,如果直接)
- reactor和線程池之間的區(qū)別是什么呢涉馅?
Kafka 的高水位和Epoch如何讓各個(gè)副本異步保持同步狀態(tài)
- 高水位 High WaterMark 是標(biāo)記消息提交和未提交的分界線归园,在hw之前的數(shù)據(jù)都可以認(rèn)為是已提交到kafka上了,否則還認(rèn)為沒有成功提交到kafka上稚矿;此處的提交是說認(rèn)為某條消息全部同步到所有副本上的時(shí)候才認(rèn)為是已提交庸诱;
-
但是hw是有延時(shí)的,為了等各個(gè)副本的進(jìn)度晤揣,這個(gè)值是所有副本中落后的消息數(shù)記錄偶翅,消息還是要不斷的提交的leader中的,因此還需要一個(gè)緩沖空間來記錄消息該寫第幾個(gè)位置碉渡,此時(shí)出現(xiàn)了LEO (log end Offset),消息可以先寫著聚谁,kafka之間慢慢同步提交的位置
高水位和LEO - 那kafka是如何移動(dòng)自己的hw和leo呢?
- leader 是如何移動(dòng)自己的leo滞诺,leader收到producer產(chǎn)生的消息的時(shí)候形导,leo會(huì)先位移標(biāo)志位
- 其他副本是如何移動(dòng)自己的leo,副本異步拉去leader中的數(shù)據(jù)习霹,然后同步自己的leo朵耕,正常情況下,這時(shí)候leader和副本之間的leo都是一樣的
- leader的hw是如何移動(dòng)的淋叶,副本在拉取leader的leo的時(shí)候阎曹,會(huì)告訴leader自己現(xiàn)在的leo在哪,因此上一步的時(shí)候,告訴leader自己的leo是0处嫌,所以leader的hw不移動(dòng)栅贴,如果一直沒有producer產(chǎn)生消息,那么在下一次同步的時(shí)候熏迹,副本會(huì)告訴leader自己的leo是1檐薯,然后leader會(huì)將所有副本的信息進(jìn)行一次保存,并獲取最小的leo注暗,作為自己的hw坛缕;也就是說副本已經(jīng)將消息同步過去了,最少同步到某個(gè)地方了捆昏,因此hw是所有副本中的最小leo
- 副本的hw是怎么移動(dòng)的呢赚楚,副本需要去找leader去同步的獲取leader的hw,也就是它需要直到當(dāng)前所有副本中的最小同步位置在哪骗卜,然后在定自己的同步位置應(yīng)該在什么地方直晨,如果獲取到leader的hw的值大于自己的leo的話,那自己就是那個(gè)最落后的膨俐,因此自己的hw就是自己的leo,否則的話罩句,副本的hw和leader的hw保持一致
- 副本如果宕機(jī)重新啟動(dòng)的時(shí)候焚刺,在0.1.1.0版本之前呢,啟動(dòng)之后门烂,找不到宕機(jī)之前的leo乳愉,直接將hw作為leo的最后值,這個(gè)認(rèn)為也是一個(gè)比較靠譜的策略屯远,但是為什么不計(jì)leo呢蔓姚,不知道,需要之后進(jìn)行源碼級(jí)別的討論慨丐,那么這就會(huì)導(dǎo)致坡脐,如果副本宕機(jī)重啟,恢復(fù)完之后房揭,開始去拉leader的數(shù)據(jù)的時(shí)候备闲,自己被選為leader了,但是自己的leo卻不是最新的捅暴,由于leader天生具有權(quán)威性恬砂,因此會(huì)認(rèn)為自己都是對(duì)的,之后原來的leader恢復(fù)的時(shí)候蓬痒,要去同步leader的數(shù)據(jù)泻骤,然后將自己的數(shù)據(jù)更新,發(fā)現(xiàn)丟了一些消息,就是副本在恢復(fù)的時(shí)候副本當(dāng)時(shí)的高水位和原始副本的leo之間的差值
- 為了改進(jìn)這個(gè)措施狱掂,之后版本對(duì)這個(gè)操作進(jìn)行了更新演痒,在恢復(fù)的時(shí)候,首先去leader上獲取先leo值符欠,并和自己的進(jìn)行對(duì)比嫡霞,如果自己落后的話,可能需要更新否則的話不動(dòng)希柿,因此需要進(jìn)行記錄自己的leo诊沪,如果能對(duì)這個(gè)管理leo的數(shù)據(jù)進(jìn)行管理的話,需要有一個(gè)確切的版本號(hào)來控制曾撤,小的版本號(hào)會(huì)被廢棄端姚,這就是epoch的設(shè)計(jì)原則,能夠?qū)崟r(shí)的直到自己到底是領(lǐng)先還是落后的標(biāo)示挤悉,切換leader渐裸;具體是有一個(gè)單調(diào)增加的版本號(hào)。每當(dāng)副本領(lǐng)導(dǎo)權(quán)發(fā)生變更時(shí)装悲,都會(huì)增加該版本號(hào)昏鹃。小版本號(hào)的 Leader 被認(rèn)為是過期 Leader,不能再行使 Leader 權(quán)力诀诊。只要每次有變化洞渤,就+1,然后其他重啟的數(shù)據(jù)都和這個(gè)保持了一致属瓣,所以數(shù)據(jù)會(huì)同步载迄;
- 副本是否更新leo的值不再依賴hw,而是實(shí)實(shí)在在的記錄值抡蛙,類似于樂觀鎖护昧,永遠(yuǎn)是最新的leo值,所以不會(huì)丟數(shù)據(jù)
- 當(dāng)一個(gè)副本掛了粗截,如何進(jìn)行恢復(fù)呢惋耙?從日志中查詢數(shù)據(jù),然后逐漸恢復(fù)熊昌,如果沒有標(biāo)識(shí)可能會(huì)落后于原始的進(jìn)度怠晴,導(dǎo)致消息的丟失!