因為在具體開發中某些環節考慮使用kafka卻擔心有消息丟失的風險,本周結合項目對kafka的消息可靠性做了一下調研和總結:
首先明確一下丟消息的定義。kafka集群中的部分或全部broker掛了,導致consumer沒有及時收到消息,這不屬於丟消息。broker掛了,只要消息全部持久化到了硬盤上,重啟broker集群之后,使消費者繼續拉取消息,消息就沒有丟失,仍然全量消費了。
以我的理解,所謂丟消息,意味着:開發人員未感知到哪些消息沒有被消費。
我把消息的丟失歸納了以下幾種情況:
1)、 producer把消息發送給broker,因為網絡抖動,消息沒有到達broker,且開發人員無感知。
解決方案:producer設置acks參數,消息同步到master之后返回ack信號,否則拋異常使應用程序感知到並在業務中進行重試發送。這種方式一定程度保證了消息的可靠性,producer等待broker確認信號的時延也不高。
2)、 producer把消息發送給broker-master,master接收到消息,在未將消息同步給follower之前,掛掉了,且開發人員無感知。
解決方案:producer設置acks參數,消息同步到master且同步到所有follower之后返回ack信號,否則拋異常使應用程序感知到並在業務中進行重試發送。這樣設置,在更大程度上保證了消息的可靠性,缺點是producer等待broker確認信號的時延比較高。
3)、 producer把消息發送給broker-master,master接收到消息,master未成功將消息同步給每個follower,有消息丟失風險。
解決方案:同上。
4)、 某個broker消息尚未從內存緩沖區持久化到磁盤,就掛掉了,這種情況無法通過ack機制感知。
解決方案:設置參數,加快消息持久化的頻率,能在一定程度上減少這種情況發生的概率。但提高頻率自然也會影響性能。
5)、consumer成功拉取到了消息,consumer掛了。
解決方案:設置手動sync,消費成功才提交。
綜上所述,集群/項目運轉正常的情況下,kafka不會丟消息。一旦集群出現問題,消息的可靠性無法完全保證。要想盡可能保證消息可靠,基本只能在發現消息有可能沒有被消費時,重發消息來解決。所以在業務邏輯中,要考慮消息的重復消費問題,對於關鍵環節,要有冪等機制。
幾條建議:
1)、如果一個業務很關鍵,使用kafka的時候要考慮丟消息的成本和解決方案。
2)、producer端確認消息是否到達集群,若有異常,進行重發。
3)、consumer端保障消費冪等性。
4)、運維保障集群運轉正常且高可用,保障網絡狀況良好。
————————————————
版權聲明:本文為CSDN博主「qrne06」的原創文章,遵循 CC 4.0 BY-SA 版權協議,轉載請附上原文出處鏈接及本聲明。
原文鏈接:https://blog.csdn.net/qrne06/article/details/94225070
