RabbitMQ結(jié)構(gòu)
- 左側(cè) P 代表 生產(chǎn)者需纳,也就是往 RabbitMQ 發(fā)消息的程序。
- 中間即是 RabbitMQ艺挪,其中包括了 交換機(jī) 和 隊(duì)列不翩。
- 右側(cè) C 代表 消費(fèi)者,也就是往 RabbitMQ 拿消息的程序麻裳。
一般的隊(duì)列服務(wù):發(fā)消息口蝠,隊(duì)列,收消息津坑,RabbitMQ在生產(chǎn)者和隊(duì)列之間加入了交換機(jī)(Exchange)妙蔗,這樣解耦了生產(chǎn)者與隊(duì)列之間的聯(lián)系,轉(zhuǎn)變?yōu)橛山粨Q機(jī)把消息根據(jù)調(diào)度策略把消息給隊(duì)列疆瑰。
為什么要使用MQ眉反?
- 異步處理
比如注冊,用戶注冊完成后需要發(fā)短信乃摹,在這里短信不是必須的禁漓,它只是一個通知。 -
流量削峰
秒殺系統(tǒng)孵睬,用戶請求寫入消息隊(duì)列播歼,設(shè)置隊(duì)列最大長度,如果超過掰读,則直接丟棄也就是用戶直接進(jìn)入錯誤頁面秘狞。
- 服務(wù)解耦
假設(shè)服務(wù)A產(chǎn)生數(shù)據(jù), 而服務(wù)B,C,D需要這些數(shù)據(jù), 那么我們就需要在A服務(wù)中直接調(diào)用B,C,D服務(wù),把數(shù)據(jù)傳遞到下游服務(wù)。如果服務(wù)越來越多蹈集,再考慮到下游服務(wù)出錯的情況烁试,處理將會越來越復(fù)雜÷K粒可以轉(zhuǎn)變?yōu)锳發(fā)布消息减响,B,C,D依照自己的需要訂閱或者不訂閱。
如果確保消息正確發(fā)送到RabbitMQ郭怪,如何確保消息接收方消費(fèi)了消息支示?
消息發(fā)送確認(rèn)
- publisher-confirms模式,該模式關(guān)系消息有沒有傳遞到Exchange鄙才,不關(guān)心從Exchange到?jīng)]到queue
- publisher-returns模式颂鸿,該模式會在消息沒有被路由到queues時(shí)將消息返回
消息消費(fèi)確認(rèn)
RabbitMQ默認(rèn)是自動確認(rèn),自動被確認(rèn)消費(fèi)會從MQ中刪除可以攒庵。
可以設(shè)置為手動確認(rèn)嘴纺,那么成功后channel.basicAck(long deliveryTag, boolean multiple);失敗后需要channel.basicNack(long deliveryTag, boolean multiple, boolean requeue);
消息基于什么傳輸败晴?
由于TCP連接的創(chuàng)建和銷毀開銷很大,且并發(fā)數(shù)受系統(tǒng)資源限制栽渴,會造成性能瓶頸尖坤。RabbitMQ使用信道的方式來傳輸數(shù)據(jù),信道(channel)是建立在真實(shí)TCP基礎(chǔ)上的虛擬連接闲擦,且每條TCP上的通道數(shù)量沒有限制糖驴。
如何避免消息重復(fù)投遞和重復(fù)消費(fèi)?
在消息生產(chǎn)時(shí)佛致,MQ內(nèi)部針對每條消息生成一個inner-msg-id,作為去重的依據(jù)辙谜。
在消息消費(fèi)時(shí)俺榆,要求消息體中必須要有一個bizId作為去重的依據(jù),避免同一條消息被重復(fù)消費(fèi)装哆。
如何確保消息不丟失罐脊?
消息持久化,前提是隊(duì)列持久化
RabbitMQ宕機(jī)重啟恢復(fù)方式是蜕琴,寫入磁盤上的持久化日志文件萍桌。
消息怎么路由?
消息提供方-->路由-->一至多個隊(duì)列
消息發(fā)布到交換器時(shí)凌简,消息將擁有一個路由鍵上炎;
通過隊(duì)列路由鍵,可以把隊(duì)列綁定到交換器上雏搂;
消息到達(dá)交換器后藕施,RabbitMQ會將消息的路由鍵與隊(duì)列的路由鍵進(jìn)行匹配。
常見的交換器有三種:
fanout:如果交換器收到消息凸郑,將會廣播到所以綁定的隊(duì)列
direct:如果路由鍵完全匹配裳食,消息被投遞到相應(yīng)的隊(duì)列
topic:可以是來自不同源頭的消息能夠到達(dá)同一隊(duì)列,使用topic交換器時(shí)芙沥,可以使用通配符诲祸。