【Message Queue - RabbitMQ】 如何保證消息可靠性?

閱讀時間約 4 分鐘

訊息傳遞的過程中有三種可能遺失的情境:

Producer端送到RabbitMQ時丟失:

  1. 外界環境問題導致: 發生網路丟包、網路故障等造成訊息丟失。
  2. 程式碼層面、配置層面導致訊息丟失。

RabbitMQ儲存的訊息丟失:

  1. 訊息沒有持久化。
  2. 磁碟意外損壞導致訊息同步失敗。

RabbitMQ送到Consumer時丟失:

消費者接收訊息後還沒來得及處理就當機。

處理方式:

為了確保訊息正確的送達RabbitMQ及Consumer正確的收到訊息,RabbitMQ為我們提供了兩種方式:
  1. 透過AMQP Transaction機制實現。
  2. 將Channel設定為confirm模式。

AMQP Transaction機制

主要有三個方法分別為:
  • txSelect(): 將當前的channel設定為transaction模式。
  • txCommit(): 提交事務。
  • txRollback(): 回滾事務。
可以看到下面流程中多了四個步驟,如此一來當資料量大的時候處理起來會比較沒有效率,因此一般應用狀況下很少採用Transaction機制。
try {
channel.txSelect();
channel.basicPublish(...);
channel.txCommit();
} catch (e) {
channel.txRollback();
}

Confirm模式 — 生產端

首先我們一樣將通道設定為Confirm模式,Confirm模式與AMQP Transaction機制只能選一個使用。
channel.confirmSelect();
Confirm模式又分為以下三種方式:
1. 普通Confirm模式: 每發送一條消息就等待服務端回應一次。
這種方式較沒效率,每次丟一個訊息就得等待通知。
try {
// 發送一條訊息
channel.basicPublish(...);
// 等待確認訊號
if(channel.waitForConfirms()){
// 發送成功
} else {
// 重送或其他處置
}
} catch(...) {
...
}
2. 批次Confirm模式: 發送一批消息後再等待服務端回應。
這種方式可以發送一批後再等待通知,乍看之下蠻有效率的,但如果訊息常常丟失,那麼我們也得批次重傳。
try {
// 發送多條訊息
for (i = 0; i < batchSize; i++) {
channel.basicPublish(...);
}
// 等待確認訊號
if(channel.waitForConfirms()){
// 發送成功
} else {
// 重送或其他處置
}
} catch(...) {
...
}
3. 異步Confirm模式: 以Listener方式等待服務端回應。
這邊以Listener的方式來獲取通知訊息,RabbitMQ會發送以下兩種通知:
  • Ack: 成功將訊息送到Queue。
  • Nack: Queue達到上限、MQ異常、磁碟寫滿…等造成未正確將訊息送到Queue。
這邊會有一種狀況是Ack、Nack都沒收到,如網路瞬斷…等,這時候就得搭配其他機制去進行重送。
try {
// 開啟Confirm模式
channel.confirmSelect();
channel.addConfirmListener(new ConfirmListener() {
public void handleAck(long deliveryTag, boolean multiple) throws IOException {
// 成功將訊息送到Queue。
}
public void handleNack(long deliveryTag, boolean multiple) throws IOException {
// Queue達到上限、MQ異常、磁碟寫滿...等。
}
});
} catch(...) {
...
}
以上都不保證100%投送到MQ,只是盡量的保證能夠送達而已,如果對於投送訊息的部份有強烈需求則可以考慮搭配Redis…等DB來維持是否送達的狀態,但勢必會捨棄一些效能。

Confirm模式 — 消費端

消費端的部份就相對單純,處理完訊息後發送ack確認訊號給RabbitMQ即可,RabbitMQ收到後就認為已經消費完成會將該訊息刪除。
為什麼會看到廣告
116會員
257內容數
哈囉,我是阿Han,是一位 👩‍💻 軟體研發工程師,喜歡閱讀、學習、撰寫文章及教學,擅長以圖代文,化繁為簡,除了幫助自己釐清思路之外,也希望藉由圖解的方式幫助大家共同學習,甚至手把手帶您設計出高品質的軟體產品。
留言0
查看全部
發表第一個留言支持創作者!
阿Han的沙龍 的其他內容
由於Go語言本身沒有提供Enum的功能, 故我們可以使用package及type的技巧來達到類似的功能,假設今天要定義季節的enum型別, 包含了「春、夏、秋、冬」四種值的時候,可以怎麼做呢? 首先我們可以用package來框住season的範圍: 然而在season.go可以定義一個字串的類型 最
我們開發程式的過程中難免會依賴DB或其他服務, 但複雜的網路環境下我們並沒有辦法確保我們發送的請求是否正確的送達, 因此我們可以在程式中加入Retry機制, 提升我們軟體的強健性。 尤其是面對NoSQL相對弱一致性的DB時更需注意, 而在Go語言, 我們可以用簡單的技巧來完成Retry的策略, 在進
一般來說我們如果將程式運行在console上,只要用ctrl + c 之類的強制中斷方式就能讓程式中止,但如果我們想要在程式運行到一半時,偵測到某些例外狀況就離開程式,可以怎麼做呢? nodejs核心模組提供了process.exit()的方法可以讓程式強制中止,但使用了這個功能之後,我們尚未完成的
由於Javascript本身設計就適合於單線程的應用, 但一般後端應用程式都會支援多個服務來處理client的請求, nodejs中也提供了cluster模組來達成此功能。 Cluster的原理很簡單,由於每個Process都只能用單核心的CPU來運行,那麼就多開幾個來幫忙處理吧! 而這個Clust
由於Go語言本身沒有提供Enum的功能, 故我們可以使用package及type的技巧來達到類似的功能,假設今天要定義季節的enum型別, 包含了「春、夏、秋、冬」四種值的時候,可以怎麼做呢? 首先我們可以用package來框住season的範圍: 然而在season.go可以定義一個字串的類型 最
我們開發程式的過程中難免會依賴DB或其他服務, 但複雜的網路環境下我們並沒有辦法確保我們發送的請求是否正確的送達, 因此我們可以在程式中加入Retry機制, 提升我們軟體的強健性。 尤其是面對NoSQL相對弱一致性的DB時更需注意, 而在Go語言, 我們可以用簡單的技巧來完成Retry的策略, 在進
一般來說我們如果將程式運行在console上,只要用ctrl + c 之類的強制中斷方式就能讓程式中止,但如果我們想要在程式運行到一半時,偵測到某些例外狀況就離開程式,可以怎麼做呢? nodejs核心模組提供了process.exit()的方法可以讓程式強制中止,但使用了這個功能之後,我們尚未完成的
由於Javascript本身設計就適合於單線程的應用, 但一般後端應用程式都會支援多個服務來處理client的請求, nodejs中也提供了cluster模組來達成此功能。 Cluster的原理很簡單,由於每個Process都只能用單核心的CPU來運行,那麼就多開幾個來幫忙處理吧! 而這個Clust
你可能也想看
Google News 追蹤
Thumbnail
這個秋,Chill 嗨嗨!穿搭美美去賞楓,裝備款款去露營⋯⋯你的秋天怎麼過?秋日 To Do List 等你分享! 秋季全站徵文,我們準備了五個創作主題,參賽還有機會獲得「火烤兩用鍋」,一起來看看如何參加吧~
Thumbnail
11/20日NVDA即將公布最新一期的財報, 今天Sell Side的分析師, 開始調高目標價, 市場的股價也開始反應, 未來一週NVDA將重新回到美股市場的焦點, 今天我們要分析NVDA Sell Side怎麼看待這次NVDA的財報預測, 以及實際上Buy Side的倉位及操作, 從
Thumbnail
Hi 大家好,我是Ethan😊 相近大家都知道保濕是皮膚保養中最基本,也是最重要的一步。無論是在畫室裡長時間對著畫布,還是在旅途中面對各種氣候變化,保持皮膚的水分平衡對我來說至關重要。保濕化妝水不僅能迅速為皮膚補水,還能提升後續保養品的吸收效率。 曾經,我的保養程序簡單到只包括清潔和隨意上乳液
Thumbnail
來到泰國一定要做的一件事絕對是按摩! 這家 Lar thai massage 不在清邁古城,也不在尼曼路,店址位於當地安安靜靜的居民區,雖然沒有高檔大氣的裝修,走的是溫馨家庭式路線。原本我已經連按了好幾天按摩,高檔跟便宜都有,可是肩背還是覺得很僵硬,來這裏按一次整個就鬆了很多。
Thumbnail
"You live for yourselves, not for humans." About trees and their feelings of sadness due to human interference.
Thumbnail
可能包含敏感內容
aurora是一家日式的情色按摩店,比一般的按摩店多出来的服务可能也就数气垫床服务了,妹子脱光了用大胸在你身上来回蹭的感觉,那种软软绵绵的感觉,让你既放松又血脉膨胀,确实是一般按摩效果无法达到的。
Thumbnail
可能包含敏感內容
什么是泰国的Massage?分两种,一种是常规的泰式足疗或者泰式按摩,价格便宜服务号。另一种是Body to Body Massage,也叫B2B Massage,当然,是由漂亮妹子给你全程服务的。价格比中国大陆的一线城市(北上广深杭)便宜多了,服务还更好,一对比下来,在国内找服务
Thumbnail
這篇文章將會講述如何使用程式腳本讀取 Input System 的玩家輸入。
Thumbnail
Ask more, not less, of those you are inviting. Ask more of them than anyone ever has. Remind them who they are and help them become that.
Thumbnail
收到了來自於本日8/10發行ALBUM「Highway X」的B'z的訊息☆ https://bz-vermillion.com/news/220512.html #Bz #HighwayX #LIVEGYM2022 #PresentX **********
Thumbnail
生命之樹想傳達的是一種身心靈保養理念,一種讓能量生生不息的四兩撥千斤,期許著每一位客戶在課程結束之後,身心都能充滿元氣的回到生活中,並且維持更長的舒適感。
Thumbnail
這個秋,Chill 嗨嗨!穿搭美美去賞楓,裝備款款去露營⋯⋯你的秋天怎麼過?秋日 To Do List 等你分享! 秋季全站徵文,我們準備了五個創作主題,參賽還有機會獲得「火烤兩用鍋」,一起來看看如何參加吧~
Thumbnail
11/20日NVDA即將公布最新一期的財報, 今天Sell Side的分析師, 開始調高目標價, 市場的股價也開始反應, 未來一週NVDA將重新回到美股市場的焦點, 今天我們要分析NVDA Sell Side怎麼看待這次NVDA的財報預測, 以及實際上Buy Side的倉位及操作, 從
Thumbnail
Hi 大家好,我是Ethan😊 相近大家都知道保濕是皮膚保養中最基本,也是最重要的一步。無論是在畫室裡長時間對著畫布,還是在旅途中面對各種氣候變化,保持皮膚的水分平衡對我來說至關重要。保濕化妝水不僅能迅速為皮膚補水,還能提升後續保養品的吸收效率。 曾經,我的保養程序簡單到只包括清潔和隨意上乳液
Thumbnail
來到泰國一定要做的一件事絕對是按摩! 這家 Lar thai massage 不在清邁古城,也不在尼曼路,店址位於當地安安靜靜的居民區,雖然沒有高檔大氣的裝修,走的是溫馨家庭式路線。原本我已經連按了好幾天按摩,高檔跟便宜都有,可是肩背還是覺得很僵硬,來這裏按一次整個就鬆了很多。
Thumbnail
"You live for yourselves, not for humans." About trees and their feelings of sadness due to human interference.
Thumbnail
可能包含敏感內容
aurora是一家日式的情色按摩店,比一般的按摩店多出来的服务可能也就数气垫床服务了,妹子脱光了用大胸在你身上来回蹭的感觉,那种软软绵绵的感觉,让你既放松又血脉膨胀,确实是一般按摩效果无法达到的。
Thumbnail
可能包含敏感內容
什么是泰国的Massage?分两种,一种是常规的泰式足疗或者泰式按摩,价格便宜服务号。另一种是Body to Body Massage,也叫B2B Massage,当然,是由漂亮妹子给你全程服务的。价格比中国大陆的一线城市(北上广深杭)便宜多了,服务还更好,一对比下来,在国内找服务
Thumbnail
這篇文章將會講述如何使用程式腳本讀取 Input System 的玩家輸入。
Thumbnail
Ask more, not less, of those you are inviting. Ask more of them than anyone ever has. Remind them who they are and help them become that.
Thumbnail
收到了來自於本日8/10發行ALBUM「Highway X」的B'z的訊息☆ https://bz-vermillion.com/news/220512.html #Bz #HighwayX #LIVEGYM2022 #PresentX **********
Thumbnail
生命之樹想傳達的是一種身心靈保養理念,一種讓能量生生不息的四兩撥千斤,期許著每一位客戶在課程結束之後,身心都能充滿元氣的回到生活中,並且維持更長的舒適感。