插曲:Kafka的HW,LEO更新原理及執行流程總結

說出你的願望吧發表於2019-12-01

前言

雖然這是一個原始碼的預熱篇同樣這也是插曲篇的一個總結,我們從一開始的叢集的各個角色,到叢集的設計,到網路模型,到生產者,消費者都已經提了個遍。這一篇會把最後的一個核心提一下,然後對以往的概念三篇做一個總結,把流程梳理一下,增加記憶的同時,也讓後面的原始碼變得更加輕鬆愉快,好的這是最後一次鴿了?。

以往連結

概念①:插曲:大白話帶你認識Kafka

實踐的:插曲:Kafka的叢集部署實踐及運維相關

概念②:插曲:Kafka的生產者原理及重要引數說明

概念③:插曲:Kafka的生產者案例和消費者原理解析

沒啥的:插曲:Kafka原始碼預熱篇--- Java NIO

一、補完上一篇Kafka中沒提完的

Kafka的生產者案例和消費者原理解析中我們提到kafka的核心裡還有個 LEO&HW 原理,現在補充回來。

1.1 LEO&HW更新原理

首先這裡有兩個Broker,也就是兩臺伺服器,然後它們的分割槽中分別儲存了兩個p0的副本,一個是leader,一個是follower

插曲:Kafka的HW,LEO更新原理及執行流程總結

此時生產者往leader partition傳送資料,資料最終肯定是要寫到磁碟上的。然後follower會從leader那裡去同步資料,follower上的資料也會寫到磁碟上

插曲:Kafka的HW,LEO更新原理及執行流程總結

可是follower是先從leader那裡去同步再寫入磁碟的,所以它磁碟上面的資料肯定會比leader的那塊少。

1.1.1 LEO是什麼

LEO(last end offset)就是該副本底層日誌檔案上的資料的最大偏移量的下一個值,所以上圖中leader那裡的LEO就是5+1 = 6,follower的LEO是5。以此類推,當我知道了LEO為10,我就知道該日誌檔案已經儲存了10條資訊,位移範圍為[0,9]

1.1.2 HW是什麼

HW(highwater mark)就是水位,它一定會小於LEO的值。這個值規定了消費者僅能消費HW之前的資料。

插曲:Kafka的HW,LEO更新原理及執行流程總結

1.1.3 流程分析

follower在和leader同步資料的時候,同步過來的資料會帶上LEO的值,可是在實際情況中有可能p0的副本可能不僅僅只有2個。此時我畫多幾個follower(p0),它們也向leader partition同步資料,帶上自己的LEO。leader partition就會記錄這些follower同步過來的LEO,然後取最小的LEO值作為HW值

插曲:Kafka的HW,LEO更新原理及執行流程總結

這個做法是保證瞭如果leader partition當機,叢集會從其它的follower partition裡面選舉出一個新的leader partition。這時候無論選舉了哪一個節點作為leader,都能保證存在此刻待消費的資料,保證資料的安全性。

那麼follower自身的HW的值如何確定,那就是follower獲取資料時也帶上leader partition的HW的值,然後和自身的LEO值取一個較小的值作為自身的HW值

插曲:Kafka的HW,LEO更新原理及執行流程總結

現在你再回想一下之前提到的ISR,是不是就更加清楚了。follower如果超過10秒沒有到leader這裡同步資料,就會被踢出ISR。它的作用就是幫助我們在leader當機時快速再選出一個leader,因為在ISR列表中的follower都是和leader同步率高的,就算丟失資料也不會丟失太多。

而且我們之前沒提到什麼情況下follower可以返回ISR中,現在解答,當follower的LEO值>=leader的HW值,就可以回到ISR

可是按照剛剛的流程確實無法避免丟失部分資料的情況,當然也是有辦法來保證資料的完整的,我們們留到原始碼篇之後進行總結的時候再提。

1.1.4 覺得圖中字比較多不好看清楚的看這個

插曲:Kafka的HW,LEO更新原理及執行流程總結

二、Kafka的流程梳理

在大白話篇中帶過大家畫,現在再來一遍。

首先來兩個Broker(這叢集好歹要超過1個伺服器才能叫叢集吧),然後它們啟動的時候會往zookeeper叢集中註冊,這時候這兩臺伺服器會搶佔一個名字叫controller的目錄,誰搶到了,誰就是controller。比如現在第一臺Broker搶到了。那它就是controller,它要監聽zookeeper中各個目錄的變化,管理整個叢集的後設資料

插曲:Kafka的HW,LEO更新原理及執行流程總結

此時我們通過客戶端來用命令來建立一個主題,這時候會有一個主題的分割槽方案寫入到zookeeper的目錄中,而在controller監聽到這個目錄寫入了分割槽方案(其實就是一些後設資料資訊)之後,它也會更改自己的後設資料資訊。之後其他的Broker也會向controller來同步後設資料。保證整個叢集的Broker的後設資料都是一致的

插曲:Kafka的HW,LEO更新原理及執行流程總結

此時再比如我們現在通過後設資料資訊得知有一個分割槽p0,leader partition在第一臺Broker,follower partition在第二臺Broker。

插曲:Kafka的HW,LEO更新原理及執行流程總結

此時生產者就該出來了,生產者需要往叢集傳送訊息前,要先把每一條訊息封裝成ProducerRecord物件,這是生產者內部完成的。之後會經歷一個序列化的過程。接下來它需要過去叢集中拉取後設資料(所以大家知道為啥在 插曲:Kafka的生產者原理及重要引數說明 的 1-⑤-1 生產者程式碼裡面為啥要提供一個或多個broker的地址了吧),當時的程式碼片段如下

props.put("bootstrap.servers", "hadoop1:9092,hadoop2:9092,hadoop3:9092");
複製程式碼

因為如果不提供伺服器的地址,是沒法獲取到後設資料資訊的。此時生產者的訊息是不知道該傳送給哪個伺服器的哪個分割槽的。

插曲:Kafka的HW,LEO更新原理及執行流程總結

此時生產者不著急把訊息傳送出去,而是先放到一個緩衝區。把訊息放進緩衝區之後,與此同時會有一個獨立執行緒Sender去把訊息分批次包裝成一個個Batch。整好一個個batch之後,就開始傳送給對應的主機上面。此時經過 大白話篇 中加餐時間所提到的Kafka的三層網路架構模型,寫到os cache,再繼續寫到磁碟上面。

之後寫磁碟的過程又要將 Kafka的生產者案例和消費者原理解析 中提到的日誌二分查詢,和剛剛才提完的ISR,LEO和HW。因為當leader寫入完成時,follower又要過去同步資料了。

此時消費者組也進來,這個消費者組會有一個它們的group.id號,根據這個可以計算出哪一個broker作為它們的coodinator,確定了coordinator之後,所有的consumer都會傳送一個join group請求註冊。之後coordinator就會預設把第一個註冊上來的consumer選擇成為leader consumer把整個Topic的情況彙報給leader consumer。之後leader consumer就會根據負載均衡的思路制定消費方案,返回給coordinator,coordinator拿到方案之後再下發給所有的consumer,完成流程。

插曲:Kafka的HW,LEO更新原理及執行流程總結

所以這樣就把我們的插曲系列中提到的所有的知識點都連起來了,基本上囊括了所有必須知道的知識點。這麼大一件事情全部都是分開一篇一篇一個個小的知識點循序漸進地闡述完整的。如果對Kafka感興趣的朋友,真的推薦把之前的那幾篇都可以讀一下,相信對你一定有所幫助。

回到原始碼的那個事兒

原始碼篇中Java NIO的基礎知識(看到沒有,基礎是重點字,不要求高階的)和scala是兩個條件,不過如果是對scala沒了解的朋友也不需要擔心,它和Java十分類似。相信配合一定的解釋的話,一定也可以看懂所有的套路。

三、簡單說說環境

Kafka的版本是0.10.1版本,最新的應該是2.2.x了。核心流程都沒太大變化,老版本相比新版本更加的穩定,老一點的版本程式碼結構會更清晰,因為像這種開源的專案,很多人都會去提交一些patch,但是提交patch的人員不一定是最優秀的那一群,會讓新的版本程式碼看起來很混亂,學習起來就自然不太方便了

1.1 JDK1.7+(這個就不說了)

1.2 scala

Kafka一開始出來的時候其原始碼是用scala寫的,但是後面producer端和consumer端的程式碼用java重寫了,但是server端的原始碼還一直用的scala寫的,所以我們分析Kafka的原始碼需要安裝scala的環境。

我使用的是2.11.8版本,下載好配置環境變數即可(通過度娘可以完美完成,和Java的配置也很相像,這裡不展開了)。

IDEA需要安裝一個scala的外掛,在Settings-plugins那裡,直接搜尋scala即可。

1.3 gradle

Kafka的原始碼沒有采用maven去管理,而是用的gradle,大家就把這個想成是一個類似於maven的程式碼管理工具即可。安裝它的方式跟安裝maven一樣。

finally

將會講到的原始碼

KafkaProducer:
    (難的,這個行了其它都是行的,而且原始碼寫的很優秀,估計要分好幾篇慢慢來)
Server:
    (有了上面的Producer之後就不會很難了)
KafkaConsumer:
    (非常基礎,不太需要講,其實大資料的框架關於讀資料的部分都不算太難)
複製程式碼

如果要一個一個類地去說明,那肯定會非常亂套的,所以要藉助場景去闡述巧了,這個場景甚至還不需要我來寫。看見原始碼裡面有個example包了嗎?大部分的大資料框架都是開源的,為了推廣,首先官方文件要寫的詳細,而且還得自己提供一些不錯的示例包才方便。從現在開始,講解基本依靠程式碼註釋。

插曲:Kafka的HW,LEO更新原理及執行流程總結

下一篇就從這裡開始。大家共勉,一起努力

相關文章