kafka如何保證數據可靠性和數據一致性


數據可靠性

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

Producer 往 Broker 發送消息

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

  • acks=0:生產者不會等待任何來自服務器的響應。

    如果當中出現問題,導致服務器沒有收到消息,那么生產者無從得知,會造成消息丟失

    由於生產者不需要等待服務器的響應所以可以以網絡能夠支持的最大速度發送消息,從而達到很高的吞吐量

  • acks=1(默認值):只要集群的Leader節點收到消息,生產者就會收到一個來自服務器的成功響應

    如果消息無法到達Leader節點(例如Leader節點崩潰,新的Leader節點還沒有被選舉出來)生產者就會收到一個錯誤響應,為了避免數據丟失,生產者會重發消息

    如果一個沒有收到消息的節點成為新Leader,消息還是會丟失

    此時的吞吐量主要取決於使用的是同步發送還是異步發送,吞吐量還受到發送中消息數量的限制,例如生產者在收到服務器響應之前可以發送多少個消息

  • acks=-1:只有當所有參與復制的節點全部都收到消息時,生產者才會收到一個來自服務器的成功響應

    這種模式是最安全的,可以保證不止一個服務器收到消息,就算有服務器發生崩潰,整個集群依然可以運行

    延時比acks=1更高,因為要等待不止一個服務器節點接收消息

根據實際的應用場景,我們設置不同的 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 列表里面就是 follower 副本的 Borker 編號,只有“跟得上” Leader 的 follower 副本才能加入到 ISR 里面,這個是通過 replica.lag.time.max.ms 參數配置的。只有 ISR 里的成員才有被選為 leader 的可能。

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

綜上所述,為了保證數據的可靠性,我們最少需要配置一下幾個參數:

  • producer 級別:acks=all(或者 request.required.acks=-1),同時發生模式為同步 producer.type=sync
  • topic 級別:設置 replication.factor>=3,並且 min.insync.replicas>=2;
  • broker 級別:關閉不完全的 Leader 選舉,即 unclean.leader.election.enable=false;

數據一致性

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

假設分區的副本為3,其中副本0是 Leader,副本1和副本2是 follower,並且在 ISR 列表里面。雖然副本0已經寫入了 Message3,但是 Consumer 只能讀取到 Message1。因為所有的 ISR 都同步了 Message1,只有 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 參數配置,它指定了副本在復制消息時可被允許的最大延遲時間。

輸入中。。。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM