1.為什麼要用訊息佇列
解耦、非同步、削峰
- A系統呼叫B系統、C系統,傳統的呼叫是直接呼叫,但是當B系統說我不需要你提供資料了,這時候A需要改程式碼,C系統說我不需要某個欄位了,這時候A也要改程式碼,如果又多了一個D系統,A又要寫程式碼。為了實現解耦,引入訊息佇列,A將產生的資料丟到訊息佇列中,哪個系統需要 哪個系統就去取;
- A系統呼叫B系統,B系統由於某個需要呼叫第三方介面超時,導致A系統響應速度慢,而B系統的好壞又不會影響業務邏輯,所以可以改為A非同步呼叫B,A將訊息丟到訊息佇列中,B系統訂閱訊息,實現A的快速響應;
- 當大量流量請求到系統A時,由於資料庫的處理能力有限,造成資料庫連線異常。使用訊息佇列,大量請求先丟到訊息佇列中,系統A使用按批拉資料的方式,批量處理資料,生產中,高峰期短暫的訊息積壓是允許的。
2.使用訊息佇列有什麼缺點
- 系統複雜性增加:加了訊息佇列,需要保證訊息不會重複消費,需要保證訊息的可靠性,需要保證訊息佇列的高可用
- 系統的可用性降低:如果訊息佇列掛了,那麼系統也會受到影響
3.為什麼選用RocketMQ;RocketMQ和ActiveMQ的區別
RocketMQ模型簡單、介面易用,在阿里大規模使用,社群活躍,單機吞吐量10萬級,可用性非常高,訊息理論上不會丟失;
- ActiveMQ嚴格遵循JMS規範,可持久化到記憶體、檔案、資料庫,可用性高主要是主從,多語言支援,消失丟失率低;
- RocketMQ持久化到磁碟檔案,可用性非常高,支援分散式,只支援Java,訊息理論上不會丟失;
4.RocketMQ是怎麼保證系統高可用的?
- 多Master部署,防止單點故障;
- 主從結構,訊息冗餘,防止訊息丟失;
5.MQ能否保證訊息必達,即訊息的可靠性?
為了降低訊息丟失的概率,MQ需要進行超時和重傳
(1) MQ-client-sender 傳送訊息給MQ-server
(2) MQ-server接收到訊息後,傳送 ACK訊息給傳送方
(3) MQ-client-sender 接收到 ACK訊息後,則 訊息已經投遞成功
如果上述 2 訊息丟失或者超時,MQ-client-sender 內的 timer 會重發訊息,直到收到 ACK訊息,如果重試N次後還未收到,則回撥傳送失敗。需要注意的是,這個過程中 MQ-server 可能會收到同一條訊息的多次重發。
對每條訊息,MQ系統內部必須生成一個inner-msg-id,作為去重和冪等的依據,這個內部訊息ID的特性是:
- 全域性唯一
- MQ生成,具備業務無關性,對訊息傳送方和訊息接收方遮蔽
(4) MQ-server 將訊息傳送給 MQ-client-receiver
(5) MQ-client-receiver 得到訊息處理業務邏輯
(6) MQ-client-receiver 回覆 ACK訊息給 MQ-server
(7) MQ-server收到 ACK訊息,將已消費的訊息刪除
如果上述 6 訊息丟失或者超時,MQ-server 內的 timer 會重發訊息,直到 MQ-server 收到ACK訊息 並且 將已消費的訊息刪除,這個過程也可能會重發多次,MQ-client-receiver 也可能會收到同一條訊息的多次重發。
需要強調的是,MQ-client-receiver 回ACK給 MQ-server,是訊息消費業務方的主動呼叫行為,不能由 MQ-client-sender 自動發起,因為MQ系統不知道消費方什麼時候真正消費成功。
為了保證業務冪等性,業務訊息體中,必須有一個biz-id,作為去重和冪等的依據,這個業務ID的特性是:
- 對於同一個業務場景,全域性唯一
- 由業務訊息傳送方生成,業務相關,對MQ透明
- 由業務訊息消費方負責判重,以保證冪等
最常見的業務ID有:支付ID,訂單ID,帖子ID等。
歡迎關注我的公眾號~ 搜尋公眾號: 翻身碼農把歌唱 或者 掃描下方二維碼: