HW
、 LEO
等概念和上一篇文章所說的 ISR
有着緊密的關系,如果不了解 ISR 可以先看下ISR相關的介紹。
HW
(High Watermark)俗稱高水位,它標識了一個特定的消息偏移量(offset),消費者只能拉取到這個offset之前的消息。
下圖表示一個日志文件,這個日志文件中只有9條消息,第一條消息的offset(LogStartOffset)為0,最有一條消息的offset為8,offset為9的消息使用虛線表示的,代表下一條待寫入的消息。日志文件的 HW 為6,表示消費者只能拉取offset在 0 到 5 之間的消息,offset為6的消息對消費者而言是不可見的。
LEO
(Log End Offset),標識當前日志文件中下一條待寫入的消息的offset。上圖中offset為9的位置即為當前日志文件的 LEO,LEO 的大小相當於當前日志分區中最后一條消息的offset值加1.分區 ISR 集合中的每個副本都會維護自身的 LEO ,而 ISR 集合中最小的 LEO 即為分區的 HW,對消費者而言只能消費 HW 之前的消息。
下面具體分析一下 ISR 集合和 HW、LEO的關系。
假設某分區的 ISR 集合中有 3 個副本,即一個 leader 副本和 2 個 follower 副本,此時分區的 LEO 和 HW 都分別為 3 。消息3和消息4從生產者出發之后先被存入leader副本。
在消息被寫入leader副本之后,follower副本會發送拉取請求來拉取消息3和消息4進行消息同步。
在同步過程中不同的副本同步的效率不盡相同,在某一時刻follower1完全跟上了leader副本而follower2只同步了消息3,如此leader副本的LEO為5,follower1的LEO為5,follower2的LEO 為4,那么當前分區的HW取最小值4,此時消費者可以消費到offset0至3之間的消息。
當所有副本都成功寫入消息3和消息4之后,整個分區的HW和LEO都變為5,因此消費者可以消費到offset為4的消息了。
由此可見kafka的復制機制既不是完全的同步復制,也不是單純的異步復制。事實上,同步復制要求所有能工作的follower副本都復制完,這條消息才會被確認已成功提交,這種復制方式極大的影響了性能。而在異步復制的方式下,follower副本異步的從leader副本中復制數據,數據只要被leader副本寫入就會被認為已經成功提交。在這種情況下,如果follower副本都還沒有復制完而落后於leader副本,然后leader副本宕機,則會造成數據丟失。kafka使用這種ISR的方式有效的權衡了數據可靠性和性能之間的關系。