1、生產者端
首先,咱們要知道生產者在生產數據時是靠ack應答機制來傳輸數據的,當session
ack=0時,生成者無需等待brokder的ack,一直髮送消息異步
ack=1時,生產者接收到leader的ack信號,就會發送下一條數據ide
ack=-1時,生產者必須等到全部broker返回ack信號,纔會發送下一條數據spa
1.1數據丟失的狀況
當ack=0時,若是有一臺broker掛掉,那麼那臺broker就會接收不到這條消息.net
當ack=1時,若是有一臺follower掛掉,那麼這臺follower也會丟失這條消息,線程
或者follower還未同步leader的數據,leader掛了,也會丟失消息code
1.2數據重複的狀況
當ack=-1時,只要有一臺follower沒有與leader同步,生產者就會從新發送消息,這就照成了消息的重複blog
1.3避免方法
開啓精確一次性,也就是冪等性,get
enable.idempotence=true
開啓後,kafka首先會讓producer自動將 acks=-1,再將producer端的retry次數設置爲Long.MaxValue,再在集羣上對每條消息進行標記去重!kafka
去重原理:
在cluster端,對每一個生產者線程生成的每條數據,都會添加由生產者id,分區號,隨機的序列號組成的標識符: (producerid,partition,SequenceId),經過標識符對數據進行去重!
可是隻能當次會話有效,若是重啓了就沒有效果
2、消費者端
消費者是以維護offset的方式來消費數據的,因此若是在提交offset的過程當中出問題,就會形成數據的問題,即已經消費了數據,可是offset沒提交
大佬博客裏已經解釋很詳細了http://www.javashuo.com/article/p-xarvecsw-n.html
注意:手動提交時,不管是同步提交仍是異步提交,都會有數據重複消費的風險
解決方案:
1.手動維護offset
2.加大這個參數kafka.consumer.session.timeout,以免被錯誤關閉的狀況
3.加大消費能力