您好,登錄后才能下訂單哦!
這篇文章主要講解了“消息隊列把消息弄丟了怎么解決”,文中的講解內容簡單清晰,易于學習與理解,下面請大家跟著小編的思路慢慢深入,一起來研究和學習“消息隊列把消息弄丟了怎么解決”吧!
消息隊列會丟失消息嗎?
答案是肯定的,所以對于業務嚴謹的數據,我們要確保其在消息隊列中的安全,不能丟。
要想解決不丟的問題,首先要弄清楚 消息是怎么丟的呢?
丟消息的關鍵點有3個:
Producer 發送消息的過程
消息隊列的消息存儲
Consumer 消費消息的過程
下面挨個看看都是怎么丟的,以及解決方案。
會以 RabbitMQ 和 Kafka 這兩個常用的消息系統來說明。
Producer 向 MQ 發消息,很簡單,發過去就完事兒了。
但是,在發送圖中是存在危險的,例如網絡問題等等,導致 MQ 沒有正常收到。
怎么解決呢? 思路很簡單,讓 MQ 發一個 接受確認聲明(ack) 就行了,就像快遞需要簽收一樣。
例如 RabbitMQ,有兩種方式可以確保發送消息的安全。
1)事務消息
Producer 發送消息之前,先開啟事務,然后再發送。
如果 RabbitMQ 沒有正常收到消息,Producer 會收到異常信息,回滾事務。
如果正常接收了,Producer 就提交事務。
很可靠,但效率低,因為這個事務模式是同步的,會產生阻塞。
2)confirm 確認模式
Producer 開啟 confirm 模式,發送消息的時候,RabbitMQ 會給這個消息分配一個唯一的 ID。
成功寫入隊列之后,RabbitMQ 會向 Producer 發送一個 ack 消息,說明此 ID 的消息已經成功發送。
confirm 模式還有一個回調機制,Producer 可以準備一個失敗的接口,供 RabbitMQ 在接收失敗時調用。
Producer 收到失敗通知,或者超時了,可以執行相應的處理邏輯,例如重發。
confirm 模式是異步的,比事務消息更高效,使用更為廣泛。
Kafka 也是使用的 ack 方式,使用方式很簡單,只要配置:
ack=all
確保 Kafka 在完全接收成功后才發送確認通知,這樣就一定不會發丟了。
MQ 成功接收消息之后,需要保存起來,等著 Consumer 消費。
在這個保存期間,也可以能丟失消息。
這通常是由 MQ 故障引起的。
RabbitMQ 想要保障消息不丟,需要開啟持久化,消息就會寫入磁盤。
即使 RabbitMQ 宕機了,只要磁盤沒事兒,重啟之后還可以重新把消息加載進來。
如果想進一步的保障消息安全,就需要配置 RabbitMQ 的鏡像集群了,來確保高可用。
Kafka 是天然的分布式系統,Topic 分為多個 Partition,每個 Partition 又有多個副本。
Partition 的多個副本,分為 Leader 和 Follower。
Leader 負責處理消息的讀寫,Follower 負責備份。
前面說的 Kafka 配置 ack=all
,就是告訴Kafka,Leader 和所有 Follower 全都接收到了,才算發送 ack 確認,只有 Leader 自己接收成功是不算的。
否則的話,如果 Leader 接收完成就告訴 Producer OK 了,在 Leader 同步給 Follower 之前,Leader 宕機了,Kafka 會從 Follower 中選舉出新的 Leader。那么,老 Leader 在臨終前沒有同步的消息就丟失了。
為了保障消息的安全,這 4 個參數要設置好:
replication.factor
用于指定 Partition 副本的數量,必須大于 1,就是至少要有 2 個副本,一個 Leader 一個 Follower。
min.insync.replicas
用于指定幾個副本成功寫入才提交消息,只有提交之后的消息才能被 Consumer 消費。
此值至少大于 1,這樣就保障 Leader 之外至少有一個副本同步到了這條消息,不怕 Leader 宕掉了。
acks=all
用于指定幾個副本接收到消息之后向 Producer 發送 ack。例如值為 1,表示 Leader 收到就可以了,“all” 表示 “所有副本”,也可以寫 “-1”,等同于 “all”。
retries=999
用于指定 Producer 發送失敗后的重試次數,可以設為一個很大的數,表示失敗了就重試,提升發送成功幾率。
例如 Consumer 成功接收到了消息 “123”,MQ 就會移除這條消息。
但在 Consumer 處理完這條消息之前,宕機了。
Consumer 重啟之后繼續從 MQ 拿消息,這次拿到的就是下一條消息 “124”,那么 “123” 就丟了。
所以,Consumer 只是接收到消息是不夠的,成功處理完成才行。
這就和 MQ 的消費確認機制有關了。
RabbitMQ 默認是 Consumer 成功接收消息之后就發送 ack 確認,RabbitMQ 就認為消費成功了。
關閉自動的 Consumer ack 就行,改為手動發送確認通知。
Kafka 的 Consumer 發送的不是 ack 確認,而是 offset,告訴 Kafka 已經消費到哪個位置了。
默認是 Consumer 接收后自動提交 offset,所以也需要關閉,改為手動提交。
小結一下,要想消息不丟,需要發消息的時候確認發送成功了,MQ 存儲的時候要是高可靠的,Consumer 消費的時候,不能接收之后就確認,真正處理完成才行。
感謝各位的閱讀,以上就是“消息隊列把消息弄丟了怎么解決”的內容了,經過本文的學習后,相信大家對消息隊列把消息弄丟了怎么解決這一問題有了更深刻的體會,具體使用情況還需要大家實踐驗證。這里是億速云,小編將為大家推送更多相關知識點的文章,歡迎關注!
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。