本文內(nèi)容思維導(dǎo)圖: “RabbitMQ?”“Kafka?”“RocketMQ?”...在日常學(xué)習(xí)與開(kāi)發(fā)過(guò)程中,我們常常聽(tīng)到消息隊(duì)列這個(gè)關(guān)鍵詞。我也在我的多篇文章中提到了這個(gè)概念。可能你是熟練使用消息隊(duì)列的老手,又或者你是不懂消息隊(duì)列的新手,不論你了不了解消息隊(duì)列,本文都將帶你搞懂消息隊(duì)列的一些基本理論。如果你是老手,你可能從本文學(xué)到你之前不曾注意的一些關(guān)于消息隊(duì)列的重要概念,如果你是新手,相信本文將是你打開(kāi)消息隊(duì)列大門的一板磚。 一 什么是消息隊(duì)列我們可以把消息隊(duì)列比作是一個(gè)存放消息的容器,當(dāng)我們需要使用消息的時(shí)候可以取出消息供自己使用。消息隊(duì)列是分布式系統(tǒng)中重要的組件,使用消息隊(duì)列主要是為了通過(guò)異步處理提高系統(tǒng)性能和削峰、降低系統(tǒng)耦合性。目前使用較多的消息隊(duì)列有ActiveMQ,RabbitMQ,Kafka,RocketMQ,我們后面會(huì)一一對(duì)比這些消息隊(duì)列。 另外,我們知道隊(duì)列 Queue 是一種先進(jìn)先出的數(shù)據(jù)結(jié)構(gòu),所以消費(fèi)消息時(shí)也是按照順序來(lái)消費(fèi)的。比如生產(chǎn)者發(fā)送消息1,2,3...對(duì)于消費(fèi)者就會(huì)按照1,2,3...的順序來(lái)消費(fèi)。但是偶爾也會(huì)出現(xiàn)消息被消費(fèi)的順序不對(duì)的情況,比如某個(gè)消息消費(fèi)失敗又或者一個(gè) queue 多個(gè)consumer 也會(huì)導(dǎo)致消息被消費(fèi)的順序不對(duì),我們一定要保證消息被消費(fèi)的順序正確。 除了上面說(shuō)的消息消費(fèi)順序的問(wèn)題,使用消息隊(duì)列,我們還要考慮如何保證消息不被重復(fù)消費(fèi)?如何保證消息的可靠性傳輸(如何處理消息丟失的問(wèn)題)?......等等問(wèn)題。所以說(shuō)使用消息隊(duì)列也不是十全十美的,使用它也會(huì)讓系統(tǒng)可用性降低、復(fù)雜度提高,另外需要我們保障一致性等問(wèn)題。 二 為什么要用消息隊(duì)列我覺(jué)得使用消息隊(duì)列主要有兩點(diǎn)好處:1.通過(guò)異步處理提高系統(tǒng)性能(削峰、減少響應(yīng)所需時(shí)間);2.降低系統(tǒng)耦合性。如果在面試的時(shí)候你被面試官問(wèn)到這個(gè)問(wèn)題的話,一般情況是你在你的簡(jiǎn)歷上涉及到消息隊(duì)列這方面的內(nèi)容,這個(gè)時(shí)候推薦你結(jié)合你自己的項(xiàng)目來(lái)回答。 《大型網(wǎng)站技術(shù)架構(gòu)》第四章和第七章均有提到消息隊(duì)列對(duì)應(yīng)用性能及擴(kuò)展性的提升。 (1) 通過(guò)異步處理提高系統(tǒng)性能(削峰、減少響應(yīng)所需時(shí)間)
通過(guò)以上分析我們可以得出消息隊(duì)列具有很好的削峰作用的功能——即通過(guò)異步處理,將短時(shí)間高并發(fā)產(chǎn)生的事務(wù)消息存儲(chǔ)在消息隊(duì)列中,從而削平高峰期的并發(fā)事務(wù)。 舉例:在電子商務(wù)一些秒殺、促銷活動(dòng)中,合理使用消息隊(duì)列可以有效抵御促銷活動(dòng)剛開(kāi)始大量訂單涌入對(duì)系統(tǒng)的沖擊。如下圖所示: 因?yàn)?strong>用戶請(qǐng)求數(shù)據(jù)寫入消息隊(duì)列之后就立即返回給用戶了,但是請(qǐng)求數(shù)據(jù)在后續(xù)的業(yè)務(wù)校驗(yàn)、寫數(shù)據(jù)庫(kù)等操作中可能失敗。因此使用消息隊(duì)列進(jìn)行異步處理之后,需要適當(dāng)修改業(yè)務(wù)流程進(jìn)行配合,比如用戶在提交訂單之后,訂單數(shù)據(jù)寫入消息隊(duì)列,不能立即返回用戶訂單提交成功,需要在消息隊(duì)列的訂單消費(fèi)者進(jìn)程真正處理完該訂單之后,甚至出庫(kù)后,再通過(guò)電子郵件或短信通知用戶訂單成功,以免交易糾紛。這就類似我們平時(shí)手機(jī)訂火車票和電影票。 (2) 降低系統(tǒng)耦合性我們知道如果模塊之間不存在直接調(diào)用,那么新增模塊或者修改模塊就對(duì)其他模塊影響較小,這樣系統(tǒng)的可擴(kuò)展性無(wú)疑更好一些。 我們最常見(jiàn)的事件驅(qū)動(dòng)架構(gòu)類似生產(chǎn)者消費(fèi)者模式,在大型網(wǎng)站中通常用利用消息隊(duì)列實(shí)現(xiàn)事件驅(qū)動(dòng)結(jié)構(gòu)。如下圖所示: 消息隊(duì)列使利用發(fā)布-訂閱模式工作,消息發(fā)送者(生產(chǎn)者)發(fā)布消息,一個(gè)或多個(gè)消息接受者(消費(fèi)者)訂閱消息。 從上圖可以看到消息發(fā)送者(生產(chǎn)者)和消息接受者(消費(fèi)者)之間沒(méi)有直接耦合,消息發(fā)送者將消息發(fā)送至分布式消息隊(duì)列即結(jié)束對(duì)消息的處理,消息接受者從分布式消息隊(duì)列獲取該消息后進(jìn)行后續(xù)處理,并不需要知道該消息從何而來(lái)。對(duì)新增業(yè)務(wù),只要對(duì)該類消息感興趣,即可訂閱該消息,對(duì)原有系統(tǒng)和業(yè)務(wù)沒(méi)有任何影響,從而實(shí)現(xiàn)網(wǎng)站業(yè)務(wù)的可擴(kuò)展性設(shè)計(jì)。 消息接受者對(duì)消息進(jìn)行過(guò)濾、處理、包裝后,構(gòu)造成一個(gè)新的消息類型,將消息繼續(xù)發(fā)送出去,等待其他消息接受者訂閱該消息。因此基于事件(消息對(duì)象)驅(qū)動(dòng)的業(yè)務(wù)架構(gòu)可以是一系列流程。 另外為了避免消息隊(duì)列服務(wù)器宕機(jī)造成消息丟失,會(huì)將成功發(fā)送到消息隊(duì)列的消息存儲(chǔ)在消息生產(chǎn)者服務(wù)器上,等消息真正被消費(fèi)者服務(wù)器處理后才刪除消息。在消息隊(duì)列服務(wù)器宕機(jī)后,生產(chǎn)者服務(wù)器會(huì)選擇分布式消息隊(duì)列服務(wù)器集群中的其他服務(wù)器發(fā)布消息。 備注: 不要認(rèn)為消息隊(duì)列只能利用發(fā)布-訂閱模式工作,只不過(guò)在解耦這個(gè)特定業(yè)務(wù)環(huán)境下是使用發(fā)布-訂閱模式的。除了發(fā)布-訂閱模式,還有點(diǎn)對(duì)點(diǎn)訂閱模式(一個(gè)消息只有一個(gè)消費(fèi)者),我們比較常用的是發(fā)布-訂閱模式。 另外,這兩種消息模型是 JMS 提供的,AMQP 協(xié)議還提供了 5 種消息模型。 三 使用消息隊(duì)列帶來(lái)的一些問(wèn)題
四 JMS VS AMQP4.1 JMS4.1.1 JMS 簡(jiǎn)介JMS(JAVA Message Service,java消息服務(wù))是java的消息服務(wù),JMS的客戶端之間可以通過(guò)JMS服務(wù)進(jìn)行異步的消息傳輸。JMS(JAVA Message Service,Java消息服務(wù))API是一個(gè)消息服務(wù)的標(biāo)準(zhǔn)或者說(shuō)是規(guī)范,允許應(yīng)用程序組件基于JavaEE平臺(tái)創(chuàng)建、發(fā)送、接收和讀取消息。它使分布式通信耦合度更低,消息服務(wù)更加可靠以及異步性。 ActiveMQ 就是基于 JMS 規(guī)范實(shí)現(xiàn)的。 4.1.2 JMS兩種消息模型①點(diǎn)到點(diǎn)(P2P)模型
② 發(fā)布/訂閱(Pub/Sub)模型
4.1.3 JMS 五種不同的消息正文格式JMS定義了五種不同的消息正文格式,以及調(diào)用的消息類型,允許你發(fā)送并接收以一些不同形式的數(shù)據(jù),提供現(xiàn)有消息格式的一些級(jí)別的兼容性。
4.2 AMQPAMQP,即Advanced Message Queuing Protocol,一個(gè)提供統(tǒng)一消息服務(wù)的應(yīng)用層標(biāo)準(zhǔn) 高級(jí)消息隊(duì)列協(xié)議(二進(jìn)制應(yīng)用層協(xié)議),是應(yīng)用層協(xié)議的一個(gè)開(kāi)放標(biāo)準(zhǔn),為面向消息的中間件設(shè)計(jì),兼容 JMS?;诖藚f(xié)議的客戶端與消息中間件可傳遞消息,并不受客戶端/中間件同產(chǎn)品,不同的開(kāi)發(fā)語(yǔ)言等條件的限制。 RabbitMQ 就是基于 AMQP 協(xié)議實(shí)現(xiàn)的。 4.3 JMS vs AMQP
總結(jié):
五 常見(jiàn)的消息隊(duì)列對(duì)比
總結(jié):
|
|