1. 結(jié)構(gòu)
消息服務(wù)器包含以下角色:
- vhost:虛擬機(jī),不同虛擬機(jī)內(nèi)可以有各自獨立的配置瞬欧,如權(quán)限
- exchange:用于消息分發(fā)
- queue:緩存消息
- route:隊列與exchange的綁定關(guān)系收苏,exchange收到消息后根據(jù)消息的route-key將消息轉(zhuǎn)發(fā)到相應(yīng)的隊列仙逻。
- channel: 在client與消息服務(wù)器之間的tcp連接中,開辟多個channel提完,每個線程使用其中一個channel粘捎,避免連接數(shù)過多薇缅。
2.工作流程
- producer產(chǎn)生消息,指定消息的exchange和routekey晌端,將消息發(fā)到指定exchange
- exchange收到消息捅暴,匹配routekey的隊列恬砂,將消息發(fā)送到隊列咧纠。
- consumer從監(jiān)聽的隊列獲取消息并消費(fèi)。
3. exchange
direct:發(fā)送到路由鍵完全匹配的隊列
fanout:廣播到當(dāng)前exchange綁定的所有隊列
topic:可使用通配符部分匹配route-key,將消息發(fā)送至匹配的隊列泻骤。
4. 可靠性保證
1.broker確認(rèn):生產(chǎn)者到broker的可靠性保證漆羔。
2.broker持久化:防止broker宕機(jī)丟失數(shù)據(jù)梧奢。
3.消費(fèi)者確認(rèn)
消費(fèi)者接收每一條消息后都必須進(jìn)行確認(rèn),只有消費(fèi)者確認(rèn)了消息演痒,RabbitMQ才能安全地把消息從隊列中刪除亲轨。這里并沒有用到超時機(jī)制,RabbitMQ僅通過Consumer的連接中斷來確認(rèn)是否需 要重新發(fā)送消息鸟顺。也就是說惦蚊,只要連接不中斷,RabbitMQ給了Consumer足夠長 的時間來處理消息讯嫂。保證數(shù)據(jù)的最終一致性蹦锋。
消費(fèi)者確認(rèn)機(jī)制有兩個須注意的問題:
(1) 如果消費(fèi)者接收到消息,在確認(rèn)之前斷開了連接或取消訂閱欧芽,RabbitMQ會 認(rèn)為消息沒有被分發(fā)莉掂,然后重新分發(fā)給下一個訂閱的消費(fèi)者。
(2) 如果消費(fèi)者接收到消息卻沒有確認(rèn)消息千扔,連接也未斷開憎妙,則RabbitMQ認(rèn)為 該消費(fèi)者繁忙,將不會給該消費(fèi)者分發(fā)更多的消息曲楚。
確認(rèn)和持久化不能完全保證可靠厘唾,broker中已確認(rèn)的消息,在節(jié)點宕機(jī)數(shù)據(jù)無法恢復(fù)時洞渤,消息發(fā)生丟失阅嘶。
解決方案:
- 方案1. 隊列需要鏡像,保證高可用
- 方案2. 消息補(bǔ)償载迄。發(fā)送讯柔、接收消息時,需要記錄消息狀態(tài)护昧,檢查是否被消費(fèi)魂迄。
5.消息重復(fù)消費(fèi)
第4節(jié)主要保證消息至少被消費(fèi)一次,但由于重發(fā)機(jī)制惋耙,消息可能會重復(fù)消費(fèi)捣炬。
解決方案:冪等性保證,消息中攜帶唯一業(yè)務(wù)id绽榛,消費(fèi)時檢查id是否已消費(fèi)湿酸。
場景:
- 插入數(shù)據(jù)庫:數(shù)據(jù)庫建立unique key約束
- 非冪等的update操作:如扣款50等更新,先檢查消息id是否已被消費(fèi)灭美。
6. 延遲隊列
- ttl
可以對queue和message分別設(shè)置ttl推溃,過期的消息稱為dead letter。 - 死信隊列
可以為死信指定交換機(jī)和route-key届腐,重新將死信進(jìn)行路由铁坎,發(fā)送到隊列處理蜂奸。 - 成為deal letter條件
- 有過期message
- 隊列長度達(dá)到最大值
- 消息被拒絕且不再重新入隊
7.工作模式
simple:一個隊列一個消費(fèi)者
worker:一個隊列多個消費(fèi)者,爭搶消息
發(fā)布訂閱:通過隊列與exchange的綁定關(guān)系完成消息分發(fā)硬萍。
8.順序消費(fèi)
需求:生產(chǎn)者產(chǎn)生一組消息扩所,組內(nèi)消息需要被順序消費(fèi)。
方案:生產(chǎn)者到隊列朴乖、隊列到消費(fèi)者都需要順序發(fā)送祖屏,并在前一條消息處理完成之后返回信號,獲取下一條消息买羞。
producer -> queue:生產(chǎn)的消息需放入本地隊列緩存赐劣,發(fā)送一條消息時加鎖;broker收到消息并發(fā)送到隊列后哩都,返回確認(rèn)魁兼;生產(chǎn)者收到確認(rèn)后釋放鎖發(fā)送下一條消息。
queue -> consumer: 同樣須加鎖漠嵌,收到消費(fèi)者的確認(rèn)后咐汞,釋放鎖發(fā)送下一條消息。
此時儒鹿,一個隊列只能有一個消費(fèi)者化撕。如果需要多個消費(fèi)者,則需要建立多個隊列约炎。生產(chǎn)者根據(jù)消息分組id求哈希值植阴,將同一分組的消息發(fā)送到相同隊列。
9.集群
普通集群:某節(jié)點掛了圾浅,則節(jié)點上消息不可用掠手,需重啟節(jié)點。
鏡像模式:同一隊列在多個節(jié)點上建立數(shù)據(jù)備份