新四季網

rabbitmq如何保證消息不丟失(RabbitMQ消息丟失)

2023-04-20 04:20:34 3

一、前言

首先說一點,企業中最常用的實際上既不是RocketMQ,也不是Kafka,而是RabbitMQ。

RocketMQ很強大,但主要是阿里推廣自己的雲產品而開源出來的一款消息隊列,其實中小企業用RocketMQ的沒有想像中那麼多。

深層次的原因在於兔寶在中小企業普及更早,經受的考驗也更久,很容易產生「回頭客」,當初隨RabbitMQ成長的一批人才如今大部分都已成為企業中的中堅骨幹,技術選型親睞RabbitMQ的機率就更高。

至於Kafka,主要還是用在大數據和日誌採集方面,除了一些公司有特定的需求會使用外,對消息收發準確率要求較高的公司依然是以RabbitMQ作為企業級消息隊列的首選。

工作這麼多年我自身的感受是,RabbitMQ經久不衰,除非後續其他消息中間件有與眾不同的使用體驗,否則依然是RabbitMQ的佔有率更高。

所以準備進入軟體行業的小夥伴,我建議有必要系統的先把RabbitMQ學好,然後再學習其他消息中間件擴展視野,他們的原理大同小異,是可以觸類旁通的。

二、兩個概念

RabbitMQ避免消息丟失的方法主要是利用消息確認機制和手動籤收機制,所以有必要把這兩個概念搞清楚。

1、消息確認機制

主要是生產者使用的機制,用來確認消息是否被成功消費。

配置如下:

這樣,當你實現RabbitTemplate.ConfirmCallback, RabbitTemplate.ReturnCallback這兩個接口的方法後,就可以針對性地進行消息確認的日誌記錄,之後做進一步的消息發送補償,以達到接近100%投遞的目的。

偽代碼如下:

2、消息籤收機制

RabbitMQ的消息是自動籤收的,你可以理解為快遞籤收了,那麼這個快遞的狀態就從發送變為已籤收,唯一的區別是快遞公司會對物流軌跡有記錄,而MQ籤收後就從隊列中刪除了。

企業級開發中,RabbitMQ我們基本都開啟手動籤收方式,這樣可以有效避免消息的丟失。

前文中已經在生產者開啟了手動籤收機制,那麼作為消費方,也要設置手動籤收。

配置如下:

消費監聽時,手動籤收就一行代碼,偽代碼如下:

三、消息丟失

兩個概念搞清楚後,就可以來學習消息丟失的問題和處理方案了。

1、出現原因

消息丟失的原因無非有三種:

1)、消息發出後,中途網絡故障,伺服器沒收到;

2)、消息發出後,伺服器收到了,還沒持久化,伺服器宕機;

3)、消息發出後,伺服器收到了,消費方還未處理業務邏輯,服務卻掛掉了,而消息也自動籤收,等於啥也沒幹。

這三種情況,(1) 和 (2)是由於生產方未開啟消息確認機制導致,(3)是由於消費方未開啟手動籤收機制導致。

2、解決方案

1)、生產方發送消息時,要try...catch,在catch中捕獲異常,並將MQ發送的關鍵內容記錄到日誌表中,日誌表中要有消息發送狀態,若發送失敗,由定時任務定期掃描重發並更新狀態;

2)、生產方publisher必須要加入確認回調機制,確認成功發送並籤收的消息,如果進入失敗回調方法,就修改資料庫消息的狀態,等待定時任務重發;

3)、消費方要開啟手動籤收ACK機制,消費成功才將消息移除,失敗或因異常情況而尚未處理,就重新入隊。

其實這就是前面闡述兩個概念時已經講過的內容,也是接近100%消息投遞的企業級方案之一,主要目的就是為了解決消息丟失的問題。

四、消息重複1、出現原因

消息重複大體上有兩種情況會出現:

1)、消息消費成功,事務已提交,籤收時結果伺服器宕機或網絡原因導致籤收失敗,消息狀態會由unack轉變為ready,重新發送給其他消費方;

2)、消息消費失敗,由於retry重試機制,重新入隊又將消息發送出去。

2、解決方案

網上大體上能搜羅到的方法有三種:

1)、消費方業務接口做好冪等;

2)、消息日誌表保存MQ發送時的唯一消息ID,消費方可以根據這個唯一ID進行判斷避免消息重複;

3)、消費方的Message對象有個getRedelivered方法返回Boolean,為TRUE就表示重複發送過來的。

我這裡只推薦第一種,業務方法冪等這是最直接有效的方式,(2)還要和資料庫產生交互,(3)有可能導致第一次消費失敗但第二次消費成功的情況被砍掉。

五、消息積壓1、出現原因

消息積壓出現的場景一般有兩種:

1)、消費方的服務掛掉,導致一直無法消費消息;

2)、消費方的服務節點太少,導致消費能力不足,從而出現積壓,這種情況極可能就是生產方的流量過大導致。

2、解決方案

1)、既然消費能力不足,那就擴展更多消費節點,提升消費能力;

2)、建立專門的隊列消費服務,將消息批量取出並持久化,之後再慢慢消費。

(1)就是最直接的方式,也是消息積壓最常用的解決方案,但有些企業考慮到伺服器成本壓力,會選擇第(2)種方案進行迂迴,先通過一個獨立服務把要消費的消息存起來,比如存到資料庫,之後再慢慢處理這些消息即可。

六、使用心得

這裡單獨講一下本人在工作中使用RabbitMQ的一些心得,希望能有所幫助。

1)、消息丟失、消息重複、消息積壓三個問題中,實際上主要解決的還是消息丟失,因為大部分公司遇不到消息積壓的場景,而稍微有水準的公司核心業務都會解決冪等問題,所以幾乎不存在消息重複的可能;

2)、消息丟失的最常見企業級方案之一就是定時任務補償,因為不論是SOA還是微服務的架構,必然會有分布式任務調度的存在,自然也就成為MQ最直接的補償方式,如果MQ一定要實現100%投遞,這種是最普遍的方案。但我實際上不推薦中小企業使用該方案,因為憑空增加維護成本,而且沒有一定規模的項目完全沒必要,大家都小看了RabbitMQ本身的性能,比如我們公司,支撐一個三甲醫院,也就是三臺8核16G伺服器的集群,上線至今3年毫無壓力;

3)、不要迷信網上和培訓機構講解的生產者消息確認機制,也就是前面兩個概念中講到的ConfirmCallback和ReturnCallback,這種機制十分降低MQ性能,我們團隊曾遇到過一次流量高峰期帶來的MQ傳輸及消費性能大幅降低的情況,後來發現是消息確認機制導致,關閉後立馬恢復正常,從此以後都不再使用這種機制,MQ運行十分順暢。同時我們會建立後臺管理實現人工補償,通過識別業務狀態判斷消費方是否處理了業務邏輯,畢竟這種情況都是少數,性能和運維成本,在這一塊我們選擇了性能;

4)、我工作這些年使用RabbitMQ沒見過自動籤收方式,一定是開啟手動籤收;

5)、手動籤收方式你在網上看到的教程幾乎都是處理完業務邏輯之後再手動籤收,但實際上這種用法是不科學的,在分布式的架構中,MQ用來解耦和轉發是非常常見的,如果是支付業務,往往在回調通知中通過MQ轉發到其他服務,其他服務如果業務處理不成功,那麼手動籤收也不執行,這個消息又會入隊發給其他消費者,這樣就可能在流量洪峰階段因為偶然的業務處理失敗造成堵塞,甚至標題所講的三種問題同時出現,這樣就會得不償失。

不科學的用法:在處理完業務邏輯後再手動籤收,否則不籤收,就好比客人進店了你得買東西,否則不讓走。

科學的用法:不論業務邏輯是否處理成功,最終都要將消息手動籤收,MQ的使命不是保證客人進店了必須消費,不消費就不讓走,而是客人能進來就行,哪怕是隨便看看也算任務完成。

可能有人會問你這樣不是和自動籤收沒區別嗎,NO,你要知道如果自動籤收,出現消息丟失你連記錄日誌的可能都沒有。

另外,為什麼一定要這麼做,因為MQ是中間件,本身就是輔助工具,就是一個滴滴司機,保證給你送到順便說個再見就行,沒必要還下車給你搬東西。

如果強加給MQ過多壓力,只會造成本身業務的畸形。我們使用MQ的目的就是解耦和轉發,不再做多餘的事情,保證MQ本身是流暢的、職責單一的即可。

七、總結

本篇主要講了RabbitMQ的三種常見問題及解決方案,同時分享了一些作者本人工作中使用的心得,我想網上是很難找到的,如果哪一天用到了,不妨再打開看看,也許能避免一些生產環境可能出現的問題。

我總結下來就是三點:

1)、消息100%投遞會增加運維成本,中小企業視情況使用,非必要不使用;

2)、消息確認機制影響性能,非必要不使用;

3)、消費者先保證消息能籤收,業務處理失敗可以人工補償。

工作中怕的永遠不是一個技術不會使用,而是遇到問題不知道有什麼解決思路。

END

私信作者回復「資源」有更多驚喜內容哦!

,
同类文章
葬禮的夢想

葬禮的夢想

夢見葬禮,我得到了這個夢想,五個要素的五個要素,水火只好,主要名字在外面,職業生涯良好,一切都應該對待他人治療誠意,由於小,吉利的冬天夢想,秋天的夢是不吉利的
找到手機是什麼意思?

找到手機是什麼意思?

找到手機是什麼意思?五次選舉的五個要素是兩名士兵的跡象。與他溝通很好。這是非常財富,它擅長運作,職業是仙人的標誌。單身男人有這個夢想,主要生活可以有人幫忙
我不怎麼想?

我不怎麼想?

我做了什麼意味著看到米飯烹飪?我得到了這個夢想,五線的主要土壤,但是Tu Ke水是錢的跡象,職業生涯更加真誠。他真誠地誠實。這是豐富的,這是夏瑞的巨星
夢想你的意思是什麼?

夢想你的意思是什麼?

你是什​​麼意思夢想的夢想?夢想,主要木材的五個要素,水的跡象,主營業務,主營業務,案子應該抓住魅力,不能疏忽,春天夢想的吉利夢想夏天的夢想不幸。詢問學者夢想
拯救夢想

拯救夢想

拯救夢想什麼意思?你夢想著拯救人嗎?拯救人們的夢想有一個現實,也有夢想的主觀想像力,請參閱週宮官方網站拯救人民夢想的詳細解釋。夢想著敵人被拯救出來
2022愛方向和生日是在[質量個性]中

2022愛方向和生日是在[質量個性]中

[救生員]有人說,在出生88天之前,胎兒已經知道哪天的出生,如何有優質的個性,將走在什麼樣的愛情之旅,將與生活生活有什么生活。今天
夢想切割剪裁

夢想切割剪裁

夢想切割剪裁什麼意思?你夢想切你的手是好的嗎?夢想切割手工切割手有一個真正的影響和反應,也有夢想的主觀想像力。請參閱官方網站夢想的細節,以削減手
夢想著親人死了

夢想著親人死了

夢想著親人死了什麼意思?你夢想夢想你的親人死嗎?夢想有一個現實的影響和反應,還有夢想的主觀想像力,請參閱夢想世界夢想死亡的親屬的詳細解釋
夢想搶劫

夢想搶劫

夢想搶劫什麼意思?你夢想搶劫嗎?夢想著搶劫有一個現實的影響和反應,也有夢想的主觀想像力,請參閱週恭吉夢官方網站的詳細解釋。夢想搶劫
夢想缺乏缺乏紊亂

夢想缺乏缺乏紊亂

夢想缺乏缺乏紊亂什麼意思?你夢想缺乏異常藥物嗎?夢想缺乏現實世界的影響和現實,還有夢想的主觀想像,請看官方網站的夢想組織缺乏異常藥物。我覺得有些東西缺失了