1. 程式人生 > >kafka冪等producer

kafka冪等producer

         眾所周知,Kafka 0.11.0.0版本正式支援精確一次處理語義(exactly once semantics,下稱EOS)。Kafka的EOS主要體現在3個方面:

  • 冪等producer:保證傳送單個分割槽的訊息只會傳送一次,不會出現重複訊息
  • 事務(transaction):保證原子性地寫入到多個分割槽,即寫入到多個分割槽的訊息要麼全部成功,要麼全部回滾
  • 流處理EOS:流處理本質上可看成是“讀取-處理-寫入”的管道。此EOS保證整個過程的操作是原子性。注意,這隻適用於Kafka Streams

  上面3種EOS語義有著不同的應用範圍,冪等producr只能保證單分割槽

上無重複訊息;事務可以保證多分割槽寫入訊息的完整性;而流處理EOS保證的是端到端(E2E)訊息處理的EOS。使用者在使用過程中需要根據自己的需求選擇不同的EOS。以下是啟用方法:

  • 啟用冪等producer:在producer程式中設定屬性enable.idempotence=true,但不要設定transactional.id。注意是不要設定,而不是設定成空字串或"null"
  • 啟用事務支援:在producer程式中設定屬性transcational.id為一個指定字串(你可以認為這是你的事務名稱,故最好起個有意義的名字),同時設定enable.idempotence=true
  • 啟用流處理EOS:在Kafka Streams程式中設定processing.guarantee=exactly_once

 

所謂冪等producer指producer.send的邏輯是冪等的,即傳送相同的Kafka訊息,broker端不會重複寫入訊息。同一條訊息Kafka保證底層日誌中只會持久化一次,既不會丟失也不會重複。冪等性可以極大地減輕下游consumer系統實現訊息去重的工作負擔,因此是非常實用的功能。值得注意的是,冪等producer提供的語義保證是有條件的:

  • 單分割槽冪等性:冪等producer無法實現多分割槽上的冪等性。如前所述,若要實現多分割槽上的原子性,需要引入事務
  • 單會話冪等性:冪等producer無法跨會話實現冪等性。即使同一個producer宕機並重啟也無法保證訊息的EOS語義

  雖然有上面兩個限制,冪等producer依然是一個非常實用的新功能。下面我們來討論下它的設計原理。如果要實現冪等性, 通常都需要花費額外的空間來儲存狀態以執行訊息去重。Kafka的冪等producer整體上也是這樣的思想。

  首先,producer物件引入了一個新的欄位:Producer ID(下稱PID),它唯一標識一個producer,當producer啟動時Kafka會為每個producer分配一個PID(64位整數),因此PID的生成和分配對使用者來說是完全透明的,使用者無需考慮PID的事情,甚至都感受不到PID的存在。其次,0.11 Kafka重構了訊息格式(有興趣的參見Kafka 0.11訊息設計),引入了序列號欄位(sequence number,下稱seq number)來標識某個PID producer傳送的訊息。和consumer端的offset類似,seq number從0開始計數並嚴格單調增加。同時在broker端會為每個PID(即每個producer)儲存該producer傳送過來的訊息batch的某些元資訊,比如PID資訊、訊息batch的起始seq number及結束seq number等。這樣每當該PID傳送新的訊息batch時,Kafka broker就會對比這些資訊,如果發生衝突(比如起始seq number和結束seq number與當前快取的相同),那麼broker就會拒絕這次寫入請求。倘若沒有衝突,那麼broker端就會更新這部分快取然後再開始寫入訊息。這就是Kafka實現冪等producer的設計思路:1. 為每個producer設定唯一的PID;2. 引入seq number以及broker端seq number快取更新機制來去重。