Kafka的ISR機制和像Raft這樣的傳統基于Quorum(法定人數)的協議之間的區別確實很微妙,但也非常重要。讓我們來分析一下為什么ISR可以減少所需的副本數量。
在采用ISR模型和(f+1)個副本數的配置下,一個Kafka分區能夠容忍最大f個節點失敗,相比于“少數服從多數”的方式所需的節點數大幅減少。實際上,為了能夠容忍f個節點失敗,“少數服從多數”的方式和ISR的方式都需要相同數量副本的確認信息才能提交消息。
比如,為了容忍1個節點失敗,“少數服從多數”需要3個副本和1個follower的確認信息,采用ISR的方式需要2個副本和1個follower的確認信息。在需要相同確認信息數的情況下,采用ISR的方式所需要的副本總數變少,復制帶來的集群開銷也就更低,“少數服從多數”的優勢在于它可以繞開最慢副本的確認信息,降低提交的延遲,而對Kafka而言,這種能力可以交由客戶端自己去選擇。
問題是:為什么它們有這么大的區別,ISR是如何實現副本數量減少的?
根本區別在于當舊的leader失效后,如何選擇新的leader。
“多數投票”系統(如 Raft)
在像Raft這樣的系統中,領導者選舉是一個在所有副本節點之間進行的去中心化、對稱的過程。
- 固定的Quorum:為了容忍?
f
?個故障,必須有?2f+1
?個副本。這個數字是數學上必需的。 - 寫入Quorum:一個寫操作只有在被復制到大多數節點(
f+1
)后才被認為是“已提交”的。 - 選舉Quorum:新領導者只有在獲得大多數節點(
f+1
)的投票后才能當選。
2f+1
?規則的奧妙在于,任何兩個多數派(Quorum)都保證會重疊。這意味著,在選舉新領導者時,投票給它的節點集合中必須包含至少一個接收了最后一次已提交寫入的節點。這個重疊的成員確保了過時的副本不能被選為領導者,從而防止數據丟失。領導者是誰的共識是在每次選舉期間由副本自己達成的。
Kafka的ISR(In-Sync Replica)模型
在Kafka中,領導者選舉是一個由一個特殊節點——Controller(控制器)——管理的中心化、非對稱的過程。
- 動態的“Quorum”(即ISR):Kafka不使用固定的多數派,而是使用一個動態的、與領導者完全同步的副本集合。這就是同步副本集(In-Sync Replica, ISR)。
- 更嚴格的寫入條件:一個寫操作只有在被復制到當前ISR中的所有副本后,才被認為是“已提交”的(即高水位線可以推進)。
- 中心化任命:當領導者失敗時,副本們不進行投票。監控所有Broker健康狀況的Controller會注意到這個故障。然后,它會查看該分區的最新已知ISR,并任命其中一個幸存的副本作為新的領導者。
正如在文檔中看到的那樣:
design.html:496-498
// ... existing code ...It is also important to optimize the leadership election process as that is the critical window of unavailability. A naive implementation of leader election would end up running an election per partition for allpartitions a node hosted when that node failed. As discussed above in the section on <a href="#replication">replication</a>, Kafka clusters have a special role known as the "controller" which isresponsible for managing the registration of brokers. If the controller detects the failure of a broker, it is responsible for electing one of the remaining members of the ISR to serve as the new leader.
// ... existing code ...
為什么這能減少副本數量
Kafka的ISR模型通過改變問題的方式,有效地“取巧”了。它將達成共識的工作從單個分區轉移到了中心化的Controller上。
- Raft?需要?
2f+1
?個副本,因為每個分區都必須能夠依靠重疊Quorum的數學保證,安全地自行選舉出新的領導者。 - Kafka?的一個分區只需要?
f+1
?個副本,因為分區副本本身不做出領導決策。它們相信Controller會任命一個新的領導者。由于ISR中的任何副本都保證擁有所有已提交的數據(得益于嚴格的寫入條件),所以Controller的選擇總是安全的。
這將容錯的負擔轉移了。數據分區可以用?f+1
?個副本容忍?f
?個故障,但現在Controller本身必須是容錯的。
這就引出了Raft在現代Kafka中的作用:
- 在?KRaft(Kafka Raft Metadata)模式下,Controller們自己組成一個Quorum,并使用Raft協議就集群元數據——包括每個分區的ISR成員——達成一致。
所以,總結一下:
- Raft:在每個分區的?
2f+1
?個對等節點之間進行去中心化選舉。 - Kafka的數據分區:使用由Controller進行的中心化領導者任命,這使得它們只需要?
f+1
?個副本即可運行。 - Kafka的Controller(在KRaft模式下):它們之間使用Raft來確保其管理的元數據(如ISR列表)的可靠性和一致性。
通過將元數據的共識與數據復制路徑分離開來,Kafka優化了常見場景(數據復制),使其在副本數量、磁盤空間和網絡流量方面更加高效。