kafka知識體系-kafka leader選舉

本系列主要講解kafka基本設計和原理分析,分以下內容:html

  1. 基本概念
  2. 消息模型
  3. kafka副本同步機制
  4. kafka文件存儲機制
  5. kafka數據可靠性和一致性保證
  6. kafka leader選舉
  7. kafka消息傳遞語義
  8. Kafka集羣partitions/replicas默認分配解析

kafka leader選舉

一條消息只有被ISR中的全部follower都從leader複製過去纔會被認爲已提交。這樣就避免了部分數據被寫進了leader,還沒來得及被任何follower複製就宕機了,而形成數據丟失。而對於producer而言,它能夠選擇是否等待消息commit,這能夠經過request.required.acks來設置。這種機制確保了只要ISR中有一個或者以上的follower,一條被commit的消息就不會丟失。算法

有一個很重要的問題是當leader宕機了,怎樣在follower中選舉出新的leader,由於follower可能落後不少或者直接crash了,因此必須確保選擇「最新」的follower做爲新的leader。一個基本的原則就是,若是leader不在了,新的leader必須擁有原來的leader commit的全部消息。這就須要作一個折中,若是leader在表名一個消息被commit前等待更多的follower確認,那麼在它掛掉以後就有更多的follower能夠成爲新的leader,但這也會形成吞吐率的降低。編程

有一個很重要的問題是當leader宕機了,怎樣在follower中選舉出新的leader,由於follower可能落後不少或者直接crash了,因此必須確保選擇「最新」的follower做爲新的leader。一個基本的原則就是,若是leader不在了,新的leader必須擁有原來的leader commit的全部消息。這就須要作一個折中,若是leader在表名一個消息被commit前等待更多的follower確認,那麼在它掛掉以後就有更多的follower能夠成爲新的leader,但這也會形成吞吐率的降低。併發

一種很是經常使用的選舉leader的方式是「少數服從多數」,Kafka並非採用這種方式。這種模式下,若是咱們有2f+1個副本,那麼在commit以前必須保證有f+1個replica複製完消息,同時爲了保證能正確選舉出新的leader,失敗的副本數不能超過f個。這種方式有個很大的優點,系統的延遲取決於最快的幾臺機器,也就是說好比副本數爲3,那麼延遲就取決於最快的那個follower而不是最慢的那個。「少數服從多數」的方式也有一些劣勢,爲了保證leader選舉的正常進行,它所能容忍的失敗的follower數比較少,若是要容忍1個follower掛掉,那麼至少要3個以上的副本,若是要容忍2個follower掛掉,必需要有5個以上的副本。也就是說,在生產環境下爲了保證較高的容錯率,必需要有大量的副本,而大量的副本又會在大數據量下致使性能的急劇降低。這種算法更多用在Zookeeper這種共享集羣配置的系統中而不多在須要大量數據的系統中使用的緣由。HDFS的HA功能也是基於「少數服從多數」的方式,可是其數據存儲並非採用這樣的方式。分佈式

實際上,leader選舉的算法很是多,好比Zookeeper的Zab、Raft以及Viewstamped Replication。而Kafka所使用的leader選舉算法更像是微軟的PacificA算法。高併發

Kafka在Zookeeper中爲每個partition動態的維護了一個ISR,這個ISR裏的全部replica都跟上了leader,只有ISR裏的成員纔能有被選爲leader的可能(unclean.leader.election.enable=false)。在這種模式下,對於f+1個副本,一個Kafka topic能在保證不丟失已經commit消息的前提下容忍f個副本的失敗,在大多數使用場景下,這種模式是十分有利的。事實上,爲了容忍f個副本的失敗,「少數服從多數」的方式和ISR在commit前須要等待的副本的數量是同樣的,可是ISR須要的總的副本的個數幾乎是「少數服從多數」的方式的一半。性能

上文提到,在ISR中至少有一個follower時,Kafka能夠確保已經commit的數據不丟失,但若是某一個partition的全部replica都掛了,就沒法保證數據不丟失了。這種狀況下有兩種可行的方案:大數據

  • 等待ISR中任意一個replica「活」過來,而且選它做爲leader
  • 選擇第一個「活」過來的replica(並不必定是在ISR中)做爲leader

若是必定要等待ISR中的replica「活」過來,那不可用的時間就可能會相對較長。並且若是ISR中全部的replica都沒法「活」過來了,或者數據丟失了,這個partition將永遠不可用。選擇第一個「活」過來的replica做爲leader,而這個replica不是ISR中的replica,那即便它並不保障已經包含了全部已commit的消息,它也會成爲leader而做爲consumer的數據源。默認狀況下,Kafka採用第二種策略,即unclean.leader.election.enable=true,也能夠將此參數設置爲false來啓用第一種策略。ui

unclean.leader.election.enable這個參數對於leader的選舉、系統的可用性以及數據的可靠性都有相當重要的影響。下面咱們來分析下幾種典型的場景。設計

若是上圖所示,假設某個partition中的副本數爲3,replica-0, replica-1, replica-2分別存放在broker0, broker1和broker2中。AR=(0,1,2),ISR=(0,1)。

設置request.required.acks=-1, min.insync.replicas=2,unclean.leader.election.enable=false。這裏講broker0中的副本也稱之爲broker0起初broker0爲leader,broker1爲follower。

1. 當ISR中的replica-0出現crash的狀況時,broker1選舉爲新的leader[ISR=(1)]
由於受min.insync.replicas=2影響,write不能服務,可是read能繼續正常服務。此種狀況恢復方案:

  • 嘗試恢復(重啓)replica-0,若是能起來,系統正常;
  • 若是replica-0不能恢復,須要將min.insync.replicas設置爲1,恢復write功能。

2. 當ISR中的replica-0出現crash,緊接着replica-1也出現了crash, 此時[ISR=(1),leader=-1]

不能對外提供服務,此種狀況恢復方案:

  • 嘗試恢復replica-0和replica-1,若是都能起來,則系統恢復正常;
  • 若是replica-0起來,而replica-1不能起來,這時候仍然不能選出leader,由於當設置unclean.leader.election.enable=false時,leader只能從ISR中選舉,當ISR中全部副本都失效以後,須要ISR中最後失效的那個副本能恢復以後才能選舉leader, 即replica-0先失效,replica-1後失效,須要replica-1恢復後才能選舉leader。保守的方案建議把unclean.leader.election.enable設置爲true,可是這樣會有丟失數據的狀況發生,這樣能夠恢復read服務。一樣須要將min.insync.replicas設置爲1,恢復write功能;
  • replica-1恢復,replica-0不能恢復,這個狀況上面遇到過,read服務可用,須要將min.insync.replicas設置爲1,恢復write功能;
  • replica-0和replica-1都不能恢復,這種狀況能夠參考情形2.

3. 當ISR中的replica-0, replica-1同時宕機,此時[ISR=(0,1)]

不能對外提供服務,此種狀況恢復方案:嘗試恢復replica-0和replica-1,當其中任意一個副本恢復正常時,對外能夠提供read服務。直到2個副本恢復正常,write功能才能恢復,或者將將min.insync.replicas設置爲1。


關於做者
愛編程、愛鑽研、愛分享、愛生活
關注分佈式、高併發、數據挖掘
如需捐贈,請掃碼

相關文章
相關標籤/搜索