【大數據嗶嗶集20210117】Kafka 的高可靠性是怎麼實現的

數據可靠性

Kafka 作爲一個商業級消息中間件,消息可靠性的重要性可想而知。本文從 Producter 往 Broker 發送消息、Topic 分區副本以及 Leader 選舉幾個角度介紹數據的可靠性。

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 在發生崩潰時仍能保證消息的持久性。

Producer 往 Broker 發送消息

如果我們要往 Kafka 對應的主題發送消息,我們需要通過 Producer 完成。前面我們講過 Kafka 主題對應了多個分區,每個分區下面又對應了多個副本;爲了讓用戶設置數據可靠性, Kafka 在 Producer 裏面提供了消息確認機制。也就是說我們可以通過配置來決定消息發送到對應分區的幾個副本纔算消息發送成功。可以在定義 Producer 時通過 acks 參數指定(在 0.8.2.X 版本之前是通過 request.required.acks 參數設置的)。

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

acks = 0:意味着如果生產者能夠通過網絡把消息發送出去,那麼就認爲消息已成功寫入Kafka。在這種情況下還是有可能發生錯誤,比如發送的對象無能被序列化或者網卡發生故障,但如果是分區離線或整個集羣長時間不可用,那就不會收到任何錯誤。在 acks=0 模式下的運行速度是非常快的(這就是爲什麼很多基準測試都是基於這個模式),你可以得到驚人的吞吐量和帶寬利用率,不過如果選擇了這種模式, 一定會丟失一些消息。

acks = 1:意味若 Leader 在收到消息並把它寫入到分區數據文件(不一定同步到磁盤上)時會返回確認或錯誤響應。在這個模式下,如果發生正常的 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。

Leader 選舉

在介紹 Leader 選舉之前,讓我們先來了解一下 ISR(in-sync replicas)列表。每個分區的 leader 會維護一個 ISR 列表,ISR 列表裏面就是 follower 副本的 Borker 編號,只有跟得上 Leader 的 follower 副本才能加入到 ISR 裏面,這個是通過 replica.lag.time.max.ms 參數配置的。只有 ISR 裏的成員纔有被選爲 leader 的可能。

2)數據一致性

這裏介紹的數據一致性主要是說不論是老的 Leader 還是新選舉的 Leader,Consumer 都能讀到一樣的數據。那麼 Kafka 是如何實現的呢?

假設分區的副本爲3,其中副本0是 Leader,副本1和副本2是 follower,並且在 ISR 列表裏面。雖然副本0已經寫入了 Message4,但是 Consumer 只能讀取到 Message2。因爲所有的 ISR 都同步了 Message2,只有 High Water Mark 以上的消息才支持 Consumer 讀取,而 High Water Mark 取決於 ISR 列表裏面偏移量最小的分區,對應於上圖的副本2,這個很類似於木桶原理。

這樣做的原因是還沒有被足夠多副本複製的消息被認爲是“不安全”的,如果 Leader 發生崩潰,另一個副本成爲新 Leader,那麼這些消息很可能丟失了。如果我們允許消費者讀取這些消息,可能就會破壞一致性。試想,一個消費者從當前 Leader(副本0) 讀取並處理了 Message4,這個時候 Leader 掛掉了,選舉了副本1爲新的 Leader,這時候另一個消費者再去從新的 Leader 讀取消息,發現這個消息其實並不存在,這就導致了數據不一致性問題。

當然,引入了 High Water Mark 機制,會導致 Broker 間的消息複製因爲某些原因變慢,那麼消息到達消費者的時間也會隨之變長(因爲我們會先等待消息複製完畢)。延遲時間可以通過參數 replica.lag.time.max.ms 參數配置,它指定了副本在複製消息時可被允許的最大延遲時間。

小編把阿里巴巴、騰訊、美團等大廠的Java和大數據面試題整理成了電子書和資源,目錄如下: 資源 鏈接: https://pan.baidu.com/s/1ifHfofjawqD9jn2lvoh0NA 提取碼: h79x 另外,微信搜索關注【import_bigdata】,回覆【資源】,還有幾百G大數據資源下載!

歡迎關注,《大數據成神之路》系列文章

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