1.消費端弄丟了數據
唯一可能導致消費者弄丟數據的情況,就是說,你消費到了這個消息,然后消費者那邊自動提交了 offset,讓 Kafka 以為你已經消費好了這個消息,但其實你才剛准備處理這個消息,你還沒處理,你自己就掛了,此時這條消息就丟咯。
這不是跟 RabbitMQ 差不多嗎,大家都知道 Kafka 會自動提交 offset,那么只要關閉自動提交 offset,在處理完之后自己手動提交 offset,就可以保證數據不會丟。但是此時確實還是可能會有重復消費,比如你剛處理完,還沒提交 offset,結果自己掛了,此時肯定會重復消費一次,自己保證冪等性就好了。
生產環境碰到的一個問題,就是說我們的 Kafka 消費者消費到了數據之后是寫到一個內存的 queue 里先緩沖一下,結果有的時候,你剛把消息寫入內存 queue,然后消費者會自動提交 offset。然后此時我們重啟了系統,就會導致內存 queue 里還沒來得及處理的數據就丟失了。
2.Kafka 弄丟了數據
這塊比較常見的一個場景,就是 Kafka 某個 broker 宕機,然后重新選舉 partition 的 leader。大家想想,要是此時其他的 follower 剛好還有些數據沒有同步,結果此時 leader 掛了,然后選舉某個 follower 成 leader 之后,不就少了一些數據?這就丟了一些數據啊。
生產環境也遇到過,我們也是,之前 Kafka 的 leader 機器宕機了,將 follower 切換為 leader 之后,就會發現說這個數據就丟了。
所以此時一般是要求起碼設置如下 4 個參數:
- 給 topic 設置
replication.factor
參數:這個值必須大於 1,要求每個 partition 必須有至少 2 個副本。 - 在 Kafka 服務端設置
min.insync.replicas
參數:這個值必須大於 1,這個是要求一個 leader 至少感知到有至少一個 follower 還跟自己保持聯系,沒掉隊,這樣才能確保 leader 掛了還有一個 follower 吧。 - 在 producer 端設置
acks=all
:這個是要求每條數據,必須是寫入所有 replica 之后,才能認為是寫成功了。 - 在 producer 端設置
retries=MAX
(很大很大很大的一個值,無限次重試的意思):這個是要求一旦寫入失敗,就無限重試,卡在這里了。
我們生產環境就是按照上述要求配置的,這樣配置之后,至少在 Kafka broker 端就可以保證在 leader 所在 broker 發生故障,進行 leader 切換時,數據不會丟失。
3. 生產者會不會弄丟數據?
如果按照上述的思路設置了 acks=all
,一定不會丟,要求是,你的 leader 接收到消息,所有的 follower 都同步到了消息之后,才認為本次寫成功了。如果沒滿足這個條件,生產者會自動不斷的重試,重試無限次。