【大數(shù)據(jù)嗶嗶集20210124】有人問(wèn)我Kafka Leader選舉?我真沒(méi)慌

一條消息只有被ISR中所有Follower都從Leader復(fù)制過(guò)去才會(huì)被認(rèn)為已提交。這樣就避免了部分?jǐn)?shù)據(jù)被寫(xiě)進(jìn)了Leader,還沒(méi)來(lái)得及被任何Follower復(fù)制就宕機(jī)了,而造成數(shù)據(jù)丟失。而對(duì)于Producer而言,它可以選擇是否等待消息commit,這可以通過(guò)request.required.acks來(lái)設(shè)置。這種機(jī)制確保了只要ISR中有一個(gè)或者以上的follower,一條被commit的消息就不會(huì)丟失。

什么是ISR?參考這里:【大數(shù)據(jù)嗶嗶集20210123】別問(wèn),問(wèn)就是Kafka高可靠

有一個(gè)很重要的問(wèn)題是當(dāng)Leader宕機(jī)了,怎樣在Follower中選舉出新的Leader,因?yàn)镕ollower可能落后很多或者直接crash了,所以必須確保選擇最新的Follower作為新的Leader。一個(gè)基本的原則就是,如果Leader不在了,新的Leader必須擁有原來(lái)的Leader commit的所有消息。這就需要做一個(gè)折中,如果Leader在一個(gè)消息被commit前等待更多的Follower確認(rèn),那么在它掛掉之后就有更多的Follower可以成為新的Leader,但這也會(huì)造成吞吐率的下降。

一種非常常用的選舉Leader的方式是“少數(shù)服從多數(shù)“,Kafka并不是采用這種方式。這種模式下,如果我們有2f+1個(gè)副本,那么在commit之前必須保證有f+1個(gè)replica復(fù)制完消息,同時(shí)為了保證能正確選舉出新的Leader,失敗的副本數(shù)不能超過(guò)f個(gè)。這種方式有個(gè)很大的優(yōu)勢(shì),系統(tǒng)的延遲取決于最快的幾臺(tái)機(jī)器,也就是說(shuō)比如副本數(shù)為3,那么延遲就取決于最快的那個(gè)Follower而不是最慢的那個(gè)?!吧贁?shù)服從多數(shù)”的方式也有一些劣勢(shì),為了保證Leader選舉的正常進(jìn)行,它所能容忍的失敗的Follower數(shù)比較少,如果要容忍1個(gè)Follower掛掉,那么至少要3個(gè)以上的副本,如果要容忍2個(gè)Follower掛掉,必須要有5個(gè)以上的副本。也就是說(shuō),在生產(chǎn)環(huán)境下為了保證較高的容錯(cuò)率,必須要有大量的副本,而大量的副本又會(huì)在大數(shù)據(jù)量下導(dǎo)致性能的急劇下降。這種算法更多用在Zookeeper這種共享集群配置的系統(tǒng)中而很少在需要大量數(shù)據(jù)的系統(tǒng)中使用的原因。HDFS的HA功能也是基于“少數(shù)服從多數(shù)”的方式,但是其數(shù)據(jù)存儲(chǔ)并不是采用這樣的方式。

實(shí)際上,Leader選舉的算法非常多,比如Zookeeper的Zab、Raft以及Viewstamped Replication。而Kafka所使用的Leader選舉算法更像是微軟的PacificA算法。

Kafka在Zookeeper中為每一個(gè)Partition動(dòng)態(tài)的維護(hù)了一個(gè)ISR,這個(gè)ISR里的所有replica都跟上了Leader,只有ISR里的成員才能有被選為L(zhǎng)eader的可能(unclean.leader.election.enable=false)。在這種模式下,對(duì)于f+1個(gè)副本,一個(gè)Kafka Topic能在保證不丟失已經(jīng)commit消息的前提下容忍f個(gè)副本的失敗,在大多數(shù)使用場(chǎng)景下,這種模式是十分有利的。事實(shí)上,為了容忍f個(gè)副本的失敗,“少數(shù)服從多數(shù)”的方式和ISR在commit前需要等待的副本的數(shù)量是一樣的,但是ISR需要的總的副本的個(gè)數(shù)幾乎是“少數(shù)服從多數(shù)”的方式的一半。

上文提到,在ISR中至少有一個(gè)Follower時(shí),Kafka可以確保已經(jīng)commit的數(shù)據(jù)不丟失,但如果某一個(gè)Partition的所有replica都掛了,就無(wú)法保證數(shù)據(jù)不丟失了。這種情況下有兩種可行的方案:

  • 等待ISR中任意一個(gè)replica“活”過(guò)來(lái),并且選它作為L(zhǎng)eader
  • 選擇第一個(gè)“活”過(guò)來(lái)的replica(并不一定是在ISR中)作為L(zhǎng)eader

這就需要在可用性和一致性當(dāng)中作出一個(gè)簡(jiǎn)單的抉擇。如果一定要等待ISR中的replica“活”過(guò)來(lái),那不可用的時(shí)間就可能會(huì)相對(duì)較長(zhǎng)。而且如果ISR中所有的replica都無(wú)法“活”過(guò)來(lái)了,或者數(shù)據(jù)丟失了,這個(gè)Partition將永遠(yuǎn)不可用。選擇第一個(gè)“活”過(guò)來(lái)的replica作為L(zhǎng)eader,而這個(gè)replica不是ISR中的replica,那即使它并不保障已經(jīng)包含了所有已commit的消息,它也會(huì)成為L(zhǎng)eader而作為Consumer的數(shù)據(jù)源。默認(rèn)情況下,Kafka采用第二種策略,即unclean.leader.election.enable=true,也可以將此參數(shù)設(shè)置為false來(lái)啟用第一種策略。

unclean.leader.election.enable這個(gè)參數(shù)對(duì)于leader的選舉、系統(tǒng)的可用性以及數(shù)據(jù)的可靠性都有至關(guān)重要的影響。下面我們來(lái)分析下幾種典型的場(chǎng)景。

file

如果上圖所示,假設(shè)某個(gè)Partition中的副本數(shù)為3,replica-0, replica-1, replica-2分別存放在Broker0, Broker1和Broker2中。AR=(0,1,2),ISR=(0,1)。
設(shè)置request.required.acks=-1, min.insync.replicas=2,unclean.leader.election.enable=false。這里將Broker0中的副本也稱(chēng)之為Broker0起初Broker0為L(zhǎng)eader,Broker1為Follower。

  • 當(dāng)ISR中的replica-0出現(xiàn)crash的情況時(shí),Broker1選舉為新的Leader[ISR=(1)],因?yàn)槭躮in.insync.replicas=2影響,write不能服務(wù),但是read能繼續(xù)正常服務(wù)。此種情況恢復(fù)方案:
  1. 嘗試恢復(fù)(重啟)replica-0,如果能起來(lái),系統(tǒng)正常;2. 如果replica-0不能恢復(fù),需要將min.insync.replicas設(shè)置為1,恢復(fù)write功能。
  • 當(dāng)ISR中的replica-0出現(xiàn)crash,緊接著replica-1也出現(xiàn)了crash, 此時(shí)[ISR=(1),leader=-1],不能對(duì)外提供服務(wù),此種情況恢復(fù)方案:
  1. 嘗試恢復(fù)replica-0和replica-1,如果都能起來(lái),則系統(tǒng)恢復(fù)正常;
  1. 如果replica-0起來(lái),而replica-1不能起來(lái),這時(shí)候仍然不能選出Leader,因?yàn)楫?dāng)設(shè)置unclean.leader.election.enable=false時(shí),leader只能從ISR中選舉,當(dāng)ISR中所有副本都失效之后,需要ISR中最后失效的那個(gè)副本能恢復(fù)之后才能選舉Leader,即replica-0先失效,replica-1后失效,需要replica-1恢復(fù)后才能選舉Leader。保守的方案建議設(shè)置unclean.leader.election.enable=true,但是這樣會(huì)有丟失數(shù)據(jù)的情況發(fā)生,這樣可以恢復(fù)read服務(wù)。同樣需要將min.insync.replicas設(shè)置為1,恢復(fù)write功能;
  2. replica-1恢復(fù),replica-0不能恢復(fù),這個(gè)情況上面遇到過(guò),read服務(wù)可用,需要將min.insync.replicas設(shè)置為1,恢復(fù)write功能;
  3. replica-0和replica-1都不能恢復(fù),這種情況可以參考情形2.
  • 當(dāng)ISR中的replica-0,replica-1同時(shí)宕機(jī),此時(shí)[ISR=(0,1)],不能對(duì)外提供服務(wù),此種情況恢復(fù)方案:嘗試恢復(fù)replica-0和replica-1,當(dāng)其中任意一個(gè)副本恢復(fù)正常時(shí),對(duì)外可以提供read服務(wù)。直到2個(gè)副本恢復(fù)正常,write功能才能恢復(fù),或者將將min.insync.replicas設(shè)置為1。

小編把阿里巴巴、騰訊、美團(tuán)等大廠的Java和大數(shù)據(jù)面試題整理成了電子書(shū)和資源,目錄如下:

資源

鏈接: https://pan.baidu.com/s/1ifHfofjawqD9jn2lvoh0NA 提取碼: h79x
另外,微信搜索關(guān)注【import_bigdata】,回復(fù)【資源】,還有幾百G大數(shù)據(jù)資源下載!

歡迎關(guān)注,《大數(shù)據(jù)成神之路》系列文章

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容