前言
副本機制就是備份機制,指的是在分散式叢集機器中儲存著相同的資料備份。
那麼副本機制的好處的是什麼呢?
- 提供資料冗餘(主要作用)
- 提供高伸縮性
- 改善資料區域性性
總之: 副本機制是kafka確保系統高可用和高持久的重要基石。
1.副本
所謂副本,本質上就是一個只能追加寫訊息的提交日誌。這些日誌被相同的分散儲存在不同的Broker上。
在實際生產上,每臺Broker都可能儲存有各個主題下不同分割槽的不同副本。因此單個Broker上存有成百上千個副本現象是非常正常的。
1.1 副本角色
既然多個Broker中儲存分割槽下的多個副本,那麼是如何保證副本當中的資料都是一致的呢?
針對這個問題,kafka的解決方案就是領導者副本機制
領導者的副本機制工作原理
- 在kafka中,副本分成兩類:領導者副本和追隨者副本。每個分割槽在建立時都要選舉一個副本,成為領導者副本,其餘的副本自動稱為追隨者副本。
- kafka中,追隨者副本是不會對外提供服務的,所有的請求都必須由領導者副本來處理。它唯一的任務就是從領導者副本非同步拉去訊息,並寫入到自己提交日誌中,從而實現與領導者副本的同步。
- 當領導者副本掛掉了,或者說所在Broker當機了,kafka可以通過Zookeeper提供的監控功能能夠實時感知到,並開啟新一輪領導者選舉,從追隨者副本中選一個作為新的領導者。老Leader副本重啟回來後,只能作為追隨者副本加入到叢集中。
一定注意上面第二點,追隨者副本是不會對外提供服務的。這也是kafka沒能提供讀操作橫向擴充套件的根本原因,而且它也不像mysql副本一樣有”抗讀“的作用,幫助領導者減輕壓力。那麼這種副本機制設計究竟有什麼好處呢?
1.2 副本機制的好處
1.方便實現“Read-your-writes”
顧名思義,就是當你使用生產者api向kafka成功寫入訊息後,就馬上使用消費者api去讀取剛才的訊息。
舉個例子,就是你剛發完一條微博,肯定是希望立馬能夠看到的。這就是Read-your-writes場景了。如果追隨者副本對外提供服務的話,由於副本同步是非同步的,因此有可能發生追隨者副本還沒有及時從領導者副本中拉取最新訊息,從而使客戶端看不到最新的訊息。
2.方便實現單調讀
什麼是單調讀。單調讀就是消費者在多次讀訊息時候,不會看到一條訊息一會兒存在一會兒不存在。
例如:如果允許追隨者副本提供讀服務,那麼假設當前有兩個追隨者副本F1,F2。生產者往領導者中傳送了訊息後,F1,F2開始非同步拉取訊息。若F1拉取成功了,而F2還未拉取成功。此時消費者第一次消費F1副本獲取最新訊息,第二次消費的時候消費到了F2副本。就獲取不到該條訊息了。這就不是單調讀一致性。所以都由Leader副本來處理請求的話,就能實現單調讀。
1.3 In-sync Replicas(ISR)
上文提及到的追隨者副本不對外提供服務,只是定期的非同步拉取訊息。既然是非同步的,那麼就存在著不可能與Leader實時同步的風險。所以kafka應該告訴我們,追隨者副本到底在什麼條件之下才算與Leader同步。
基於這個想法,kafka引入了ISR,副本集合。ISR中的副本都是與Leader同步的副本,相反,不在ISR中的追隨者副本被認為是與Leader不同步的。那麼進入ISR到底需要滿足什麼條件才能進入呢。
首先需要明確一點。ISR不只是追隨者副本集合,它必然包括Leader副本。甚至在某些情況下,ISR只有Leader這一個副本。
圖中有3個副本:1個領導者副本,2個追隨者副本。領導者副本寫入了10條訊息,F1同步了6條,F3同步了3條。那麼哪個追隨者副本與Leader不同步呢?
事實上,這兩個副本都有可能與Leader副本不同步,但也可能同步。它實際上不是依靠與訊息條數來進行判斷的。而是根據Broker端引數replica.lag.time.max.ms引數值。這個引數的含義就是Follower副本能夠落後Leader副本的最長時間間隔,當前預設值是10秒。
這就是說,只要一個 Follower 副本落後 Leader 副本的時間不連續超過 10 秒,那麼 Kafka 就認為該 Follower 副本與 Leader 是同步的,即使此時 Follower 副本中儲存的訊息明顯少於 Leader 副本中的訊息。若是同步過程的速度持續慢於Leadr副本的寫入速度,那麼在replica.lag.time.max.ms時間後,kafka就會自動收縮ISR集合,將改副本提出集合。
值得注意的是,若改副本後面慢慢追上了Leader的進度。那麼它是可以被重新放入ISR集合中的。這也表明ISR是一個動態調整的集合,而非靜態不變的。
Unclean 領導者選舉
既然ISR可以動態調整,那麼就會出現ISR為空的情況。ISR為空的情況就代表Leader副本也掛掉了。那麼kafka就需要重新選舉新的Leader。
那麼該怎麼選舉Leader呢?
- kafka把所有不在ISR的存活副本都成為非同步副本。
- 通常來說,非同步副本落後Leader太多,因此,如果選擇這些副本為新的Leader,就可能出現資料的丟失。在kafka,選舉Leader這種過程被成為Unclean。由Broker端引數unclean.leader.election.enable控制是否允許Unclean領導者選舉。
- 開啟 Unclean 領導者選舉可能會造成資料丟失,但好處是,它使得分割槽 Leader 副本一直存在,不至於停止對外提供服務,因此提升了高可用性。反之,禁止 Unclean 領導者選舉的好處在於維護了資料的一致性,避免了訊息丟失,但犧牲了高可用性。
可以根據你的實際業務場景決定是否開啟 Unclean 領導者選舉。不過並不建議開啟它,畢竟我們還可以通過其他的方式來提升高可用性。如果為了這點兒高可用性的改善,犧牲了資料一致性,那就非常不值當了。