Kafka消息交付
Kafka消息交付可靠性保障以及精確處理一次語義的實現。
所謂的消息交付可靠性保障,是指Kafka對Producer和Consumer要處理的消息提供什么樣的承諾。常見的承諾有以下三種:
最多一次(atmost once):消息可能會丟失,但絕不會被重復發送。
至少一次(at least once):消息不會丟失,但有可能被重復發送。
精確一次(exactly once):消息不會丟失,也不會被重復發送。
Kafka默認提供的交付可靠性保障是第二種,即至少一次。之前說過消息“已提交”的含義。即只有Broker成功“提交”消息且Producer接到Broker的應答才會認為該消息成功發送,如果沒接到應答,則會重試,所以這會導致消息重復發送。
冪等性(Idempotence)和事務(Transaction)
無論是至少一次還是最多一次,都不如精確一次。即使Producer端重復發送了相同的消 息,Broker端也能做到自動去重。在下游Consumer看來,消息依然只有一條。
Kafka的精確一次是通過兩種機制:冪等性(Idempotence)和事務(Transaction)。
冪等性Producer
Producer默認不是冪等性的,但我們可以創建冪等性Producer。僅需要設置一個參數即
// enable.idempotence被設置成true后,Producer自動升級成冪等性Producer
props.put(“enable.idempotence”, ture)
// 或者
props.put(ProducerConfig.ENABLE_IDEMPOTENCE_CONFIG, true)
冪等性Producer的作用范圍:
它只能保證單分區上的冪等性,即一個冪等性Producer能夠保證某個主題的一個分區上不出現重復消息,它無法實現多個分區的冪等性。其次,它只能實現單會話上的冪等性,不能實現跨會話的冪 等性。這里的會話,可以理解為Producer進程的一次運行。當重啟了Producer進程之后,這種冪等性保證就喪失了。
如果想實現多分區以及多會話上的消息無重復,應該使用事務(transaction)或者依賴事務型Producer。這也是冪等性Producer和事務型Producer的最大區別!
事務
Kafka的事務概念類似于我們熟知的數據庫提供的事務。Kafka對事務的支持,目前主要是在read committed隔離級別上做事情。它能保證多條消息原子性地寫入到目標分區,同時也能保證Consumer只能看到事務成功提交的消息。
事務型Producer
事務型Producer能夠保證將消息原子性地寫入到多個分區中。這批消息要么全部寫入成功,要么全部失敗。另外,事務型Producer也不懼進程的重啟。Producer重啟回來后,Kafka依然保證它們發送消息的精確一次處理。
設置事務型Producer的方法也很簡單,滿足兩個要求即可:
? ? ? ? * 和冪等性Producer一樣,開啟enable.idempotence = true。
? ? ? ? * 設置Producer端參數transactional.id。最好為其設置一個有意義的名字。
還需要在Producer代碼中做一些調整
producer.initTransactions();
try {producer.beginTransaction();producer.send(record1);producer.send(record2);producer.commitTransaction();
} catch (KafkaException e) {producer.abortTransaction();
}
這段代碼能夠保證Record1和Record2被當作一個事務統一提交到Kafka,要么它們全部提交成功,要么全部寫入失敗。實際上即使寫入失敗,Kafka也會把它們寫入到底層的日志中,也就是說Consumer還是會看到這些消息。
因此在Consumer端,讀取事務型Producer發送的消息也是需要一些變更的。修改起來也很簡單,設置isolation.level參數的值即可。當前這個參數有兩個取值:
1. read_uncommitted:這是默認值,表明Consumer能夠讀取到Kafka寫入的任何消息,不論事務型Producer提交事務還是終止事務,其寫入的消息都可以讀取。很顯然,如果你用了事務型Producer,那么對應的Consumer就不要使用這個值。
2. read_committed:表明Consumer只會讀取事務型Producer成功提交事務寫入的消息。當然了,它也能看到非事務型Producer寫入的所有消息。
總結:
冪等性Producer只能保證單分區、單會話上的消息冪等性;而 事務能夠保證跨分區、跨會話間的冪等性。從交付語義上來看,自然是事務型Producer能做的更多。
?但比起冪等性Producer,事務型Producer的性能要更差,在實際使用過程中,我們需要仔細評估引入事務的開銷,切不可無腦地啟用事務。
參考:11 | 無消息丟失配置怎么實現?-Kafka核心技術與實戰-極客時間 (geekbang.org)