一條消息只有被ISR中全部Follower都從Leader複製過去纔會被認爲已提交。這樣就避免了部分數據被寫進了Leader,還沒來得及被任何Follower複製就宕機了,而形成數據丟失。而對於Producer而言,它能夠選擇是否等待消息commit,這能夠經過request.required.acks來設置。這種機制確保了只要ISR中有一個或者以上的follower,一條被commit的消息就不會丟失。算法
什麼是ISR?參考這裏:【大數據嗶嗶集20210123】別問,問就是Kafka高可靠性能
有一個很重要的問題是當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功能也是基於「少數服從多數」的方式,可是其數據存儲並非採用這樣的方式。ui
實際上,Leader選舉的算法很是多,好比Zookeeper的Zab、Raft以及Viewstamped Replication。而Kafka所使用的Leader選舉算法更像是微軟的PacificA算法。blog
Kafka在Zookeeper中爲每個Partition動態的維護了一個ISR,這個ISR裏的全部replica都跟上了Leader,只有ISR裏的成員纔能有被選爲Leader的可能(unclean.leader.election.enable=false)。在這種模式下,對於f+1個副本,一個Kafka Topic能在保證不丟失已經commit消息的前提下容忍f個副本的失敗,在大多數使用場景下,這種模式是十分有利的。事實上,爲了容忍f個副本的失敗,「少數服從多數」的方式和ISR在commit前須要等待的副本的數量是同樣的,可是ISR須要的總的副本的個數幾乎是「少數服從多數」的方式的一半。token
上文提到,在ISR中至少有一個Follower時,Kafka能夠確保已經commit的數據不丟失,但若是某一個Partition的全部replica都掛了,就沒法保證數據不丟失了。這種狀況下有兩種可行的方案:ci
這就須要在可用性和一致性當中做出一個簡單的抉擇。若是必定要等待ISR中的replica「活」過來,那不可用的時間就可能會相對較長。並且若是ISR中全部的replica都沒法「活」過來了,或者數據丟失了,這個Partition將永遠不可用。選擇第一個「活」過來的replica做爲Leader,而這個replica不是ISR中的replica,那即便它並不保障已經包含了全部已commit的消息,它也會成爲Leader而做爲Consumer的數據源。默認狀況下,Kafka採用第二種策略,即unclean.leader.election.enable=true,也能夠將此參數設置爲false來啓用第一種策略。get
unclean.leader.election.enable這個參數對於leader的選舉、系統的可用性以及數據的可靠性都有相當重要的影響。下面咱們來分析下幾種典型的場景。it
若是上圖所示,假設某個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。io
- 嘗試恢復(重啓)replica-0,若是能起來,系統正常;2. 若是replica-0不能恢復,須要將min.insync.replicas設置爲1,恢復write功能。
- 嘗試恢復replica-0和replica-1,若是都能起來,則系統恢復正常;
歡迎關注,《大數據成神之路》系列文章
歡迎關注,《大數據成神之路》系列文章
歡迎關注,《大數據成神之路》系列文章