聊聊 Kafka:Kafka 如何保證可靠性

一、前言

在如今的分布式環境時代,任何一款中間件產品,大多都有一套機制去保證高可用的,Kafka 作為一個商業級消息中間件,消息可靠性的重要性可想而知,那 Kafka 如何保證可靠性的呢?本文從 Producer 往 Broker 發送消息、Topic 分區副本以及 Leader 選舉幾個角度介紹 Kafka 是如何保證可靠性的。

二、Producer 往 Broker 發送消息

如果我們要往 Kafka 對應的主題發送消息,我們需要通過 Producer 完成。前面我們講過 Kafka 主題對應了多個分區,每個分區下面又對應了多個副本;為了讓用戶設置數據可靠性, Kafka 在 Producer 里面提供了消息確認機制。把選項提供給用戶自己去選擇,我們可以通過配置來決定消息發送到對應分區的幾個副本才算消息發送成功。可以在定義 Producer 時通過 acks 參數指定(在 0.8.2.X 版本之前是通過 request.required.acks 參數設置的,詳見 KAFKA-3043)。

這個參數支持以下三種值:

  • acks = 0:意味著如果生產者能夠通過網絡把消息發送出去,那么就認為消息已成功寫入 Kafka 。在這種情況下還是有可能發生錯誤,比如發送的對象無能被序列化或者網卡發生故障,但如果是分區離線或整個集群長時間不可用,那就不會收到任何錯誤。在 acks=0 模式下的運行速度是非常快的(這就是為什么很多基準測試都是基于這個模式),你可以得到驚人的吞吐量和帶寬利用率,不過如果選擇了這種模式, 一定會丟失一些消息。
  • acks = 1:意味著 Leader 在收到消息并把它寫入到本地磁盤時會返回確認或錯誤響應,不管其它的 Follower 副本有沒有同步過這條消息。在這個模式下,如果發生正常的 Leader 選舉,生產者會在選舉時收到一個 LeaderNotAvailableException 異常,如果生產者能恰當地處理這個錯誤,它會重試發送消息,最終消息會安全到達新的 Leader 那里。不過在這個模式下仍然有可能丟失數據,比如消息已經成功寫入 Leader,但在消息被復制到 Follower 副本之前 Leader發生崩潰。
  • acks = all(這個和 request.required.acks = -1 含義一樣):意味著 Leader 在返回確認或錯誤響應之前,會等待所有同步副本都收到消息。如果和 min.insync.replicas 參數結合起來,就可以決定在返回確認前至少有多少個副本能夠收到消息,生產者會一直重試直到消息被成功提交。不過這也是最慢的做法,因為生產者在繼續發送其他消息之前需要等待所有副本都收到當前的消息。

根據實際的應用場景,我們設置不同的 acks,以此保證數據的可靠性。

另外,Producer 發送消息還可以選擇同步(默認,通過 producer.type=sync 配置) 或者異步(producer.type=async)模式。如果設置成異步,雖然會極大的提高消息發送的性能,但是這樣會增加丟失數據的風險。如果需要確保消息的可靠性,必須將 producer.type 設置為 sync。

三、Topic 分區副本

在 Kafka 0.8.0 之前,Kafka 是沒有副本的概念的,那時候人們只會用 Kafka 存儲一些不重要的數據,因為沒有副本,數據很可能會丟失。但是隨著業務的發展,支持副本的功能越來越強烈,所以為了保證數據的可靠性,Kafka 從 0.8.0 版本開始引入了分區副本(詳情請參見 KAFKA-50)。也就是說每個分區可以人為的配置幾個副本(比如創建主題的時候指定 replication-factor,也可以在 Broker 級別進行配置 default.replication.factor),一般會設置為 3。

Kafka 可以保證單個分區里的事件是有序的,分區可以在線(可用),也可以離線(不可用)。在眾多的分區副本里面有一個副本是 Leader,其余的副本是 Follower,所有的讀寫操作都是經過 Leader 進行的,同時 Follower 會定期地去 Leader 上的復制數據。當 Leader 掛了的時候,其中一個 Follower 會重新成為新的 Leader。通過分區副本,引入了數據冗余,同時也提供了 Kafka 的數據可靠性。

Kafka 的分區多副本架構是 Kafka 可靠性保證的核心,把消息寫入多個副本可以使 Kafka 在發生崩潰時仍能保證消息的持久性。

四、Leader 選舉

在介紹 Leader 選舉之前,讓我們先來了解一下 ISR(in-sync replicas)列表。每個分區的 Leader 會維護一個 ISR 列表,ISR 列表里面包括 Leader 副本和 Follower 副本的 Broker 編號,只有跟得上 Leader 的 Follower 副本才能加入到 ISR 里面,這個是通過 replica.lag.time.max.ms 參數配置的,這個參數的含義是 Follower 副本能夠落后 Leader 副本的最長時間間隔,默認值是 10 秒。這就是說,只要一個 Follower 副本落后 Leader 副本的時間不連續超過 10 秒,那么 Kafka 就認為該 Follower 副本與 Leader 是同步的,即使此時 Follower 副本中保存的消息明顯少于 Leader 副本中的消息。

我們在前面說過,Follower 副本唯一的工作就是不斷地從 Leader 副本拉取消息,然后寫入到自己的提交日志中。如果這個同步過程的速度持續慢于 Leader 副本的消息寫入速度,那么在 replica.lag.time.max.ms 時間后,此 Follower 副本就會被認為是與 Leader 副本不同步的,因此不能再放入 ISR 中。此時,Kafka 會自動收縮 ISR 集合,將該副本“踢出”ISR。

值得注意的是,倘若該副本后面慢慢地追上了 Leader 的進度,那么它是能夠重新被加回 ISR 的。這也表明,ISR 是一個動態調整的集合,而非靜態不變的。

所以當 Leader 掛掉了,而且 unclean.leader.election.enable=false 的情況下,Kafka 會從 ISR 列表中選擇第一個 Follower 作為新的 Leader,因為這個分區擁有最新的已經 committed 的消息。通過這個可以保證已經 committed 的消息的數據可靠性。

五、思考

Q1:對于數據的讀寫操作都在 Leader 副本中,Follower 副本只從 Leader 副本復制數據,不對外提供數據讀寫操作,只做數據冗余保證可靠性。假如 Follower 副本還沒同步完,此時 Leader 副本掛掉了,怎么保證數據的可靠性?
A1:這就要看上面說的 Producer 通過 acks 參數,根據自己的業務場景,設置不同的參數,以此保證數據的可靠性。


Q2:acks = 1,意味著 Leader 在收到消息并把它寫入到本地磁盤時會返回確認或錯誤響應,不管其它的 Follower 副本有沒有同步過這條消息。假如 Follower 副本還沒同步完,此時 Leader 副本掛掉了,怎么保證數據的可靠性?
A2:這就要看上面說的 Producer 通過 acks 參數,根據自己的業務場景,設置不同的參數,以此保證數據的可靠性。


Q3:acks = all,意味著 Leader 在返回確認或錯誤響應之前,會等待所有同步副本都收到消息。如果 Follower 副本同步完成后,Broker 給 Producer 返回 ack 之前,Leader 副本掛掉了,怎么保證數據的可靠性?
A3:數據發送到 Leader 副本后,部分 ISR 同步完成,也就是部分在 ISR 列表中的 Follower 副本同步完成后,此時 Leader 副本掛掉了,每個 Follower 副本都有可能成為新的 Leader 副本,Producer 端會返回異常,可以設置讓 Producer 端重新發送數據來保證數據的可靠性,不過可能會造成數據的重復,如果要保證數據的一致性的話,業務下游需要做冪等操作,防止數據重復消費。


Q4:acks = all,就可以代表數據一定不會丟失嗎?
A4

  • Partition 只有一個副本,也就是只有一個 Leader 副本,沒有任何一個 Follower 副本的時候,接收完消息后宕機,還是會存在數據丟失。
  • acks = all,必須跟 ISR 列表里至少有兩個以上的副本配合使用,min.insync.replicas 這個參數是設置 ISR 中最小副本數是多少,默認值是 1,改為 >= 2,如果 ISR 列表中的副本數小于 min.insync.replicas 配置的數量時,Producer 客戶端會返回異常。

Q5:acks = all 時,ISR 列表中有三個副本,一個 Leader 副本,兩個 Follower 副本。 min.insync.replicas 配置的是 2,比如 Leader 副本和 Follower 1 副本收到消息,此時 Leader 副本掛掉了,就返回異常給 Producer 了,但 Follower 2 副本選舉成 Leader 副本了,Follower 2 副本落后 Leader 副本和 Follower 1 副本一些消息,雖然都是在同一個 ISR 列表中,但 Follower 2 副本沒有落后超過 replica.lag.time.max.ms 配置的值(默認是 10s)就還算是同步副本,Follower 2 副本當選 Leader 副本,前面的消息豈不是丟失了?
A5:社區在 0.11 版本正式引入了 Leader Epoch 概念,來規避因高水位更新錯配導致的各種不一致問題。

  • Epoch。一個單調增加的版本號。每當副本領導權發生變更時,都會增加該版本號。小版本號的 Leader 被認為是過期 Leader,不能再行使 Leader 權力。
  • 起始位移(Start Offset)。Leader 副本在該 Epoch 值上寫入的首條消息的位移。

舉個例子來說明一下 Leader Epoch。假設現在有兩個 Leader Epoch<0, 0> 和 <1, 120>,那么,第一個 Leader Epoch 表示版本號是 0,這個版本的 Leader 從位移 0 開始保存消息,一共保存了 120 條消息。之后,Leader 發生了變更,版本號增加到 1,新版本的起始位移是 120。

這樣就可以保證 Follower 2 副本選舉成 Leader 副本時,沿用之前的舊的 Leader 副本的最后的消息位移。

?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 228,606評論 6 533
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 98,582評論 3 418
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 176,540評論 0 376
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 63,028評論 1 314
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 71,801評論 6 410
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 55,223評論 1 324
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,294評論 3 442
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 42,442評論 0 289
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 48,976評論 1 335
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 40,800評論 3 354
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 42,996評論 1 369
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,543評論 5 360
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 44,233評論 3 347
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,662評論 0 26
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 35,926評論 1 286
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 51,702評論 3 392
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 47,991評論 2 374

推薦閱讀更多精彩內容