kafka 提供三種語義的傳遞:
1至少一次
2至多一次
3精確一次
首先在 producer 端保證1和2的語義是非常簡單的,至少一次只需要同步確認即可(確認方式分爲只需要 leader 確認以及所有副本都確認,第二種更加具有容錯性),至多一次最簡單只需要異步不斷的發送即可,效率也比較高。目前在 producer 端還不能保證精確一次,在未來有可能實現,實現方式如下:在同步確認的基礎上爲每一條消息加一個主鍵,如果發現主鍵曾經接受過,則丟棄。
在 consumer 端,大家都知道可以控制 offset,所以可以控制消費,其實 offset 只有在重啓的時候纔會用到。在機器正常運行時我們用的是 position,我們實時消費的位置也是 position 而不是 offset。我們可以得到每一條消息的 position。如果我們在處理消息之前就將當前消息的 position 保存到 zk 上即 offset,這就是隻多一次消費,因爲我們可能保存成功後,消息還沒有消費機器就掛了,當機器再打開時此消息就丟失了;或者我們可以先消費消息然後保存 position 到 zk 上即 offset,此時我們就是至少一次,因爲我們可能在消費完消息後offset 沒有保存成功。而精確一次的做法就是讓 position的保存和消息的消費成爲原子性操作,比如將消息和 position 同時保存到 hdfs 上 ,此時保存的 position 就稱爲 offset,當機器重啓後,從 hdfs重新讀入offset,這就是精確一次。
---------------------------------------------------------------------------------
以下爲2017年10月27日更新:
由於最近又在使用kafka,但是驚喜的發現kafka官方的java client文檔的consumer的API說明中已經給出了,如何在kafka之外自己維護offset。可見,大家對精確一次的消費還是有需求的。鏈接如下:http://kafka.apache.org/0110/javadoc/index.html?org/apache/kafka/clients/consumer/KafkaConsumer.html
截圖如下: