一、前言
現在大多都使用 MQ 來做系統的異構,來做系統的解耦,系統的的模塊相當於寄信者與收信者,MQ 則扮演者郵局的角色。作爲一箇中轉的角色,就需要確保消息的100%投遞。
今天我們就來研究一下如何確保消息的100%的投遞。
二、先談談 RabbitMQ 的特性
RabbitMQ 所做的確保是:只要你把消息投遞到 Broker 中,那麼我就確保這個消息會送達到消費者的手中。
當然這是有前提條件的,比如:
- 你需要進行手動應答,
- 最起碼 Broker 不掛,且消息進行了持久化等。
結合 RabbitMQ 的特性來做分析,針對於投遞端,我們只需要確保把消息發送到 Broker 中即可,那麼如何保證可靠性呢,分下列步驟:
- 消息成功的發送了出去
- 保證 Broker 成功的收到了消息
- 生產者收到了 Broker 的確認應答
- 消息補償機制,當前三步都跪了,做一個補償重發機制
- 最後一道屏障,如果第四步重試次數過多,那麼說明系統出現問題,我們就需要人工干預了
只要做到上面五步,基本上我們就可以保證,消息投遞100%的投遞出去。
三、生產者的投遞的可靠性保障
3.1 先上一個示意圖
3.2 就上述的圖示,我們逐步解析
- step1:數據落庫,這一步是必須的
- step2:把消息落庫,且初始化其狀態爲 0 (發送中)
- step3:把消息投遞到 Broker 中
- step4:Broker 發送成功應答
- step5:生產者拿到成功應答,修改消息狀態爲1:(發送成功) 上面講述的都是正常的流程,下面講講如果出現不正常的解決機制:
- step6:定時檢查消息的狀態是否爲1
- step7:如果 step6 的消息的狀態仍然爲 0 ,則進入重發,重複上述 step1 - step5
- step8:如果消息重發達到一定的的次數,則人工接入處理,因爲此時說明可能是消息
上述的方案看似完美無缺,但是細想,如果在 step4 中 Broker 發送應答的過程中,網絡出現問題這個消息沒有到達生產者會導致整個流程進入補償的流程當中,此時 Broker 中就有兩條消息,也就是發成了重複的投遞的問題,所以接下來我們要在消費端來處理這個問題。
四、消費端的冪等:
4.1 導致需要解決冪等的原因
- Broker 發送應答消息的時候,消息未到達生產者
- 消費者在發送應答的時候,消費者掛掉了
4.2 就上述我們的機制的解決
因爲上述我的消息都有唯一的標識,所以我們只需要查找對應的消息對應的標識來判斷其狀態即可
4.3 構建唯一標識的方案
首先說明不同的方案使用不同的應用場景,不要一上來你就說十幾萬的併發怎麼樣的,這個慢慢來,一步步往這裏走
4.3.1 利用數據庫自增id
優點:
1):不能再簡單了,在併發不大的情況可以接受 2):對分頁和排序是有幫助的
缺點:
1):分庫分表和讀寫分離多住從的情況下不適用 2):性能達不到要求時,不利於擴展 3):不同數據庫的語法實現不一樣
4.3.2 利用 redis 來生成id
優點:
1):redis 單線程可以生成全局唯一ID 2):可以使用 redis 集羣獲取更高的吞吐量
缺點:
1):引入新的組件,增加系統複雜度 2):需要注意處理併發問題
4.3.3 利用 twitter 開源的 snowflake
snowflake 是 twitter 開源的一個分佈式的 ID 的生成算法,結果是一個 long 的ID,使用 41bit 作爲毫秒數,10bit 作爲機器 ID(5個 bit 是數據中心,5個 bit 是機器 ID) 12 bit 作爲毫秒內的流水號(每個節點每毫秒可以產生 2^12 = 4096 個 ID)最後是一個符號位,
優點:
1):不依賴數據庫和其他的中間件,且性能尚可
缺點:
1):是有依賴時間的,如果各個機器的失重不同步就會出現不適全局遞增的情況
最後,關注公衆號Java技術棧,在後臺回覆:面試,可以獲取我整理的 RabbitMQ 系列面試題和答案,非常齊全。
作者:熱心市民小陳
鏈接:blog.csdn.net/weixin_42849915/article/details/87828163
版權聲明:本文爲博主原創文章,遵循 CC 4.0 BY-SA 版權協議,轉載請附上原文出處鏈接和本聲明。
近期熱文推薦:
1.600+ 道 Java面試題及答案整理(2021最新版)
2.終於靠開源項目弄到 IntelliJ IDEA 激活碼了,真香!
3.阿里 Mock 工具正式開源,幹掉市面上所有 Mock 工具!
4.Spring Cloud 2020.0.0 正式發佈,全新顛覆性版本!
覺得不錯,別忘了隨手點贊+轉發哦!