面試官:對于 MQ 中的消息丟失你是如何理解的?
相信很多的小伙伴在面試的時候,涉及到MQ的面試題,消息丟失是必問面試題之一。那么對于消息丟失你又是如何理解的呢?
下面我們一起來看一下。
本文以 Kafka 舉例說明。
一、什么是消息丟失?
消息丟失的定義是:在消息傳遞的過程中,在某個環節意外丟失,也就是消息沒有成功的發送或者沒有被正確的接收。
生產者未能成功發送消息。
消費者未能正確接收消息。
消費者未能正確處理消息。
對于第三條可以理解為特殊的消息丟失,因為消費者的邏輯處理錯誤,程序bug等其他原因,造成消息在處理過程中消息丟失或者被忽略(異常之后錯誤的應答等),也就是說消息沒有正確的被消費掉,我們也可以認為是一種消息丟失。
二、消息丟失的原因有哪些
1.消息生產階段
- 生產者配置錯誤:生產者在發送消息時,配置錯誤的主體、分區或者消息的過期時間,造成消息無法正確發送到MQ中。
- 網絡故障:生產者與MQ集群之間網絡故障。
2.消息存儲階段
- 磁盤故障:以Kafka舉例,如果磁盤出現故障,Kafka中的消息無法洛盤,可能導致消息的丟失。
- 日志壓縮策略:使用了壓縮比較高的壓縮策略從而可能在壓縮的過程中丟失消息。
3.消息消費階段
- 消費者處理失敗:在處理消費邏輯時,由于程序bug等原因,造成系統異常,錯誤應答從而丟失消息。
- 消費者提交偏移量錯誤:當消費者消費完消息之后,提交錯誤的偏移量造成消息的重復消費或者消息丟失。
三、消息丟失的解決方案有哪些
1.消息生產階段
(1) 配置正確的主體、分區、以及TTL。
(2) 使用ACK應答,等待消息被MQ寫入成功之后在確認為發送成功。
- ack=1:默認值,leader副本成功寫入消息即發送成功。
- ack=0:發送消息后不等待服務端確認。
- ack=-1或者ack=all:生產者需要等待ISR中的所有副本都成功寫入消息才為消息發送成功。
(3) 消息發送重試。
- retries:配置生產者發送消息重試次數。
(4) 配置合理的壓縮策略。
- compression.type 支持none、gzip、snappy、lz4、zstd。
(5) 設置合理的消息緩沖區大小。
- buffer.memory:默認33554432。生產者用于緩存一批發送到服務器消息的總內存字節數。
(6) 使用合適的序列化器,防止序列號錯誤造成消息丟失。
其他的配置可以參考官網 Kafka 生產者配置:https://kafka.apache.org/documentation/#producerconfigs
2.消息存儲階段
- 配置適當的副本數量和ISR。在發生故障的時候消息仍然可以從其他的副本中進行恢復。
- 使用監控,實時檢測消息的復制、磁盤的使用率。
- 定期備份。
3.消息消費階段
(1) 編寫健壯的代碼,說的容易,寫起來還是得多測試。對于可能產生的異常原因進行分析處理。當發生異常時,可以做如下處理:
- 記錄錯誤,有異常處理機制,保證能夠正確的處理異常情況。
- 消息重試消息。(需要注意消費冪等以及死循環造成消息堆積)
(2) 使用手動提交偏移量。(需保證所有的異常情況代碼中都有對應的異常處理機制,也就是第一點,健壯的代碼)
(3) 使用自動提交偏移量。(需要保證消費邏輯正確)
(4) 使用監控,監控消費者的消費情況,發現異常立即上報。
(5) 正確的消費者組管理,類似消費者重平衡或者重啟等造成的消息偏移量丟失。
(6) 備份,發生異常或者消息丟失時,可以跟蹤到消費者的消費情況,直接使用備份恢復。
總結
上面我們分析了什么是消息丟失,產生的原因有哪些以及如何解決。通過看完這篇文章相信你對Kafka中的消息丟失也有了一定的了解,在工作中使用的時候也就不會沒有底氣了。
相信有眼尖的小伙伴發現了,在消費者的處理邏輯中,多次消費會造成消息的多次重復消費。消息的重試也有可能造成消息的堆積。那么這些問題就是下節課我們要說的。