kafka中的ISR、AR又代表什麼?ISR伸縮又是什麼?

​ 分區中的所有副本統稱爲AR(Assigned Repllicas)。所有與leader副本保持一定程度同步的副本(包括Leader)組成ISR(In-Sync Replicas),ISR集合是AR集合中的一個子集。消息會先發送到leader副本,然後follower副本才能從leader副本中拉取消息進行同步,同步期間內follower副本相對於leader副本而言會有一定程度的滯後。前面所說的“一定程度”是指可以忍受的滯後範圍,這個範圍可以通過參數進行配置。與leader副本同步滯後過多的副本(不包括leader)副本,組成OSR(Out-Sync Relipcas),由此可見:AR=ISR+OSR。在正常情況下,所有的follower副本都應該與leader副本保持一定程度的同步,即AR=ISR,OSR集合爲空。

​ Leader副本負責維護和跟蹤ISR集合中所有的follower副本的滯後狀態,當follower副本落後太多或者失效時,leader副本會把它從ISR集合中剔除。如果OSR集合中follower副本“追上”了Leader副本,之後再ISR集合中的副本纔有資格被選舉爲leader,而在OSR集合中的副本則沒有機會(這個原則可以通過修改對應的參數配置來改變

​ ISR的伸縮:

​ Kafka在啓動的時候會開啓兩個與ISR相關的定時任務,名稱分別爲“isr-expiration"和”isr-change-propagation".。isr-expiration任務會週期性的檢測每個分區是否需要縮減其ISR集合。這個週期和“replica.lag.time.max.ms”參數有關。大小是這個參數一半。默認值爲5000ms,當檢測到ISR中有是失效的副本的時候,就會縮減ISR集合。如果某個分區的ISR集合發生變更, 則會將變更後的數據記錄到ZooKerper對應/brokers/topics//partition//state節點中。節點中數據示例如下:

{“controller_cpoch":26,“leader”:0,“version”:1,“leader_epoch”:2,“isr”:{0,1}}

​ 其中controller_epoch表示的是當前的kafka控制器,epoch.leader表示當前分區的leader副本所在的broker的id編號,version表示版本號,(當前半本固定位1),leader_epoch表示當前分區的leader紀元,isr表示變更後的isr列表。

​ 除此之外,當ISR集合發生變更的時候還會將變更後的記錄緩存到isrChangeSet中,isr-change-propagation任務會週期性(固定值爲2500ms)地檢查isrChangeSet,如果發現isrChangeSet中有ISR 集合的變更記錄,那麼它會在Zookeeper的/isr_change_notification的路徑下創建一個以isr_change開頭的持久順序節點(比如/isr_change_notification/isr_change_0000000000), 並將isrChangeSet中的信息保存到這個節點中。kafka控制器爲/isr_change_notification添加了一個Watcher,當這個節點中有子節點發生變化的時候會觸發Watcher動作,以此通知控制器更新相關的元數據信息並向它管理的broker節點發送更新元數據信息的請求。最後刪除/isr_change_notification的路徑下已經處理過的節點。頻繁的觸發Watcher會影響kafka控制器,zookeeper甚至其他的broker性能。爲了避免這種情況,kafka添加了指定的條件,當檢測到分區ISR集合發生變化的時候,還需要檢查一下兩個條件:

​ (1).上一次ISR集合發生變化距離現在已經超過5秒,

​ (2).上一次寫入zookeeper的時候距離現在已經超過60秒。

​ 滿足以上兩個條件之一者可以將ISR寫入集合的變化的目標節點。

​ 有縮減就會有補充,那麼kafka何時擴充ISR的?

​ 隨着follower副本不斷進行消息同步,follower副本LEO也會逐漸後移,並且最終趕上leader副本,此時follower副本就有資格進入ISR集合,追趕上leader副本的判定準則是此副本的LEO是否小於leader副本HW,這裏並不是和leader副本LEO相比。ISR擴充之後同樣會更新ZooKeeper中的/broker/topics//partition//state節點和isrChangeSet,之後的步驟就和ISR收縮的時的相同。

​ 當ISR集合發生增減時,或者ISR集合中任一副本LEO發生變化時,都會影響整個分區的HW。

​ 如下圖所示,leader副本的LEO爲9,follower副本的LEO爲7,而follower2副本的LEO爲6,如果判定這三個副本都處於ISR集合中,那麼分區的HW爲6,如果follower3已經判定失效副本被剝離出ISR集合,那麼此時分區HW爲leader副本和follower副本中LEO的最小值,即爲7.

在這裏插入圖片描述

​ LW是Low Watermark的縮寫,俗稱“低水位”,代表AR集合中最小的logStartOffset值,副本的拉取請求(FetchRequest,它有可能觸發新建日誌分段而舊的的被清理,進而導致logStartoffset的增加)和刪除請求(DeleteRecordRequest)都可能促使LW的增長。

kafka中的HW、LEO、LSO、LW等分別代表什麼?

​ ISR與HW和LEO也有緊密的關係,HW是High Watermak的縮寫, 俗稱高水位,它表示了一個特定消息的偏移量(offset),消費之只能拉取到這個offset之前的消息。

​ 如下,它代表一個日誌文件,這個日誌文件中有9條消息,第一消息的offset(LogStartOffset)爲0,最後的一條消息offset爲8,offset爲9的消息用虛線框表示,代表下的一個待寫入的消息日誌文件的HW爲6.表示消費者只能拉取到offset0至5之間的消息,而offset爲6的消息對消費者而言是不可見的。

在這裏插入圖片描述

​ LEO是Log End Offset的縮寫,它表示了當前日誌文件中下一條待寫入消息的offset,如上圖offset爲9的位置即爲當前日誌文件LEO,LEO的大小相當於當前日誌分區中最後一條消息的offset值加1分區ISR集合中的每個副本都會維護自身的LEO,而ISR集合中最小的LEO即爲分區的HW,對消費者而言只能消費HW之前的消息。

​ 如下圖,假設某個分區的ISR集合中有三個副本,即一個leader副本和兩個follower副本,此時分區的LEO和HW都爲3。消息3和消息4從生產者發出之後會被先存入leader副本。

在這裏插入圖片描述

在這裏插入圖片描述

在消息寫入leader副本之後,follower副本會發送拉取請求來拉取消息3和消息4以進行消息同步。

​ 在同步過程中,不同的follower副本的同步效率也不盡相同。如下圖,在某一時刻follower1完全跟上了leader副本,而follower2只同步了消息3,如此leader副本的LEO爲5,follower1的LEO爲5,Follower2的LEO爲4。那麼當前分區的HW最小值4,此時消費者可以消費到offset爲0-3之間的消息。

​ 寫入消息如下圖,所有的副本都成功寫入了消息3和消息4,整個分區的HW和LEO爲5,因此消費者可以消費offset爲4的消息了。

在這裏插入圖片描述

​ 由此可見,kafka的複製機制不是完全的同步複製,也不是單純的異步複製,事實上,同步複製要求所有能工作的Follower副本都複製完,這條消息纔會被確認爲成功提交,這種複製方式影響了性能。而在異步複製的情況下, follower副本異步地從leader副本中複製數據,數據只要被leader副本寫入就被認爲已經成功提交。在這種情況下,如果follower副本都沒有複製完而落後於leader副本,如果突然leader副本宕機,則會造成數據丟失。Kafka使用這種ISR的方式有效的權衡了數據可靠性與性能之間的關係。

​ 什麼是LSO?

​ LSO特指LastStableOffset。它具體與kafka的事物有關。

 ​ 消費端參數——isolation.level,這個參數用來配置消費者事務的隔離級別。字符串類型,“read_uncommitted”和“read_committed”,表示消費者所消費到的位置,如果設置爲“read_committed",那麼消費這就會忽略事務未提交的消息,既只能消費到LSO(LastStableOffset)的位置,默認情況下,”read_uncommitted",既可以消費到HW(High Watermak)的位置。

注:follower副本的事務隔離級別也爲“read_uncommitted",並且不可修改。

​ 在開啓kafka事務的同時,生產者發送了若干消息,(msg1,msg2,)到broker中,如果生產者沒有提交事務(執行CommitTransaction),那麼對於isolation.level=read_committed的消費者而言是看不多這些消息的,而isolation.level=read_uncommitted則可以看到。事務中的第一條消息的位置可以標記爲firstUnstableOffset(也就是msg1的位置)。

​ 這個LSO還會影響到kafka消費之後的量,(也就是kafka,Log,很多時候也稱之爲kafka堆積量)的計算 。如下圖。

​ 在這裏插入圖片描述

​ 在圖中,對每一個分區而言,它Lag等於HW-ConsumerOffset的值,其中ComsmerOffset表示當前的消費的位移,當然這只是針對普通的情況。如果爲消息引入了事務,那麼Lag的計算方式就會有所不同。

如果當消費者客戶端的isolation.level的參數配置爲“read_uncommitted"(默認),那麼Lag的計算方式不受影響,如果這個參數配置爲“read_committed",那麼就要引入LSO來進行計算了。

在這裏插入圖片描述

​ 對於未完成的事務而言,LSO的值等於事務中的第一條消息所在的位置,(firstUnstableOffset)

​ 對於已經完成的事務而言,它的值等同於HW相同,所以我們可以得出一個結論:LSO≤HW≤LEO

在這裏插入圖片描述

​ 所以,對於分區中未完成的事務,並且消費者客戶端的isolation.level參數配置爲”read_committed

"的情況,它對應的Lag等於LSO-ComsumerOffset的值。
 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章