掃二維碼與項(xiàng)目經(jīng)理溝通
我們?cè)谖⑿派?4小時(shí)期待你的聲音
解答本文疑問(wèn)/技術(shù)咨詢/運(yùn)營(yíng)咨詢/技術(shù)建議/互聯(lián)網(wǎng)交流
消息隊(duì)列已經(jīng)逐漸成為企業(yè)應(yīng)用系統(tǒng)內(nèi)部通信的核心手段。它具有低耦合、可靠投遞、廣播、流量控制、最終一致性等一系列功能。

專業(yè)成都網(wǎng)站建設(shè)公司,做排名好的好網(wǎng)站,排在同行前面,為您帶來(lái)客戶和效益!成都創(chuàng)新互聯(lián)公司為您提供成都網(wǎng)站建設(shè),五站合一網(wǎng)站設(shè)計(jì)制作,服務(wù)好的網(wǎng)站設(shè)計(jì)公司,做網(wǎng)站、網(wǎng)站制作負(fù)責(zé)任的成都網(wǎng)站制作公司!
當(dāng)前使用較多的消息隊(duì)列有 RabbitMQ、RocketMQ、ActiveMQ、Kafka、ZeroMQ、MetaMQ 等,而部分?jǐn)?shù)據(jù)庫(kù)如 Redis、MySQL 以及 PhxSQL 也可實(shí)現(xiàn)消息隊(duì)列的功能。
消息隊(duì)列概述
消息隊(duì)列是指利用高效可靠的消息傳遞機(jī)制進(jìn)行與平臺(tái)無(wú)關(guān)的數(shù)據(jù)交流,并基于數(shù)據(jù)通信來(lái)進(jìn)行分布式系統(tǒng)的集成。
通過(guò)提供消息傳遞和消息排隊(duì)模型,它可以在分布式環(huán)境下提供應(yīng)用解耦、彈性伸縮、冗余存儲(chǔ)、流量削峰、異步通信、數(shù)據(jù)同步等等功能,其作為分布式系統(tǒng)架構(gòu)中的一個(gè)重要組件,有著舉足輕重的地位。
消息隊(duì)列的特點(diǎn)
采用異步處理模式
消息發(fā)送者可以發(fā)送一個(gè)消息而無(wú)須等待響應(yīng)。消息發(fā)送者將消息發(fā)送到一條虛擬的通道(主題或隊(duì)列)上,消息接收者則訂閱或是監(jiān)聽(tīng)該通道。
一條信息可能最終轉(zhuǎn)發(fā)給一個(gè)或多個(gè)消息接收者,這些接收者都無(wú)需對(duì)消息發(fā)送者做出同步回應(yīng)。整個(gè)過(guò)程都是異步的。
應(yīng)用系統(tǒng)之間解耦合
主要體現(xiàn)在如下兩點(diǎn):
比如在線交易系統(tǒng)為了保證數(shù)據(jù)的最終一致,在支付系統(tǒng)處理完成后會(huì)把支付結(jié)果放到消息中間件里,通知訂單系統(tǒng)修改訂單支付狀態(tài)。兩個(gè)系統(tǒng)是通過(guò)消息中間件解耦的。
消息隊(duì)列的傳遞服務(wù)模型
消息隊(duì)列的傳遞服務(wù)模型如下圖所示:
消息隊(duì)列的的傳輸模式
點(diǎn)對(duì)點(diǎn)模型
點(diǎn)對(duì)點(diǎn)模型用于消息生產(chǎn)者和消息消費(fèi)者之間點(diǎn)到點(diǎn)的通信。消息生產(chǎn)者將消息發(fā)送到由某個(gè)名字標(biāo)識(shí)的特定消費(fèi)者。
這個(gè)名字實(shí)際上對(duì)于消費(fèi)服務(wù)中的一個(gè) 隊(duì)列( Queue),在消息傳遞給消費(fèi)者之前它被存儲(chǔ)在這個(gè)隊(duì)列中。
隊(duì)列消息可以放在內(nèi)存中也可以持久化,以保證在消息服務(wù)出現(xiàn)故障時(shí)仍然能夠傳遞消息。
傳統(tǒng)的點(diǎn)對(duì)點(diǎn)消息中間件通常由消息隊(duì)列服務(wù)、消息傳遞服務(wù)、消息隊(duì)列和消息應(yīng)用程序接口 API 組成。
其典型的結(jié)構(gòu)如下圖所示:
特點(diǎn)如下:
示意圖如下所示:
發(fā)布/訂閱模型(Pub/Sub)
發(fā)布者/訂閱者模型支持向一個(gè)特定的消息主題生產(chǎn)消息。0 或多個(gè)訂閱者可能對(duì)接收來(lái)自特定消息主題的消息感興趣。
在這種模型下,發(fā)布者和訂閱者彼此不知道對(duì)方,就好比是匿名公告板。這種模式被概括為:多個(gè)消費(fèi)者可以獲得消息,在發(fā)布者和訂閱者之間存在時(shí)間依賴性。
發(fā)布者需要建立一個(gè)訂閱( Subscription),以便消費(fèi)者能夠訂閱。訂閱者必須保持持續(xù)的活動(dòng)狀態(tài)并接收消息。
在這種情況下,在訂閱者未連接時(shí),發(fā)布的消息將在訂閱者重新連接時(shí)重新發(fā)布,如下圖所示:
特性如下:
注意以下三點(diǎn):
消息隊(duì)列應(yīng)用場(chǎng)景
當(dāng)你需要使用消息隊(duì)列時(shí),首先需要考慮它的必要性??梢允褂孟㈥?duì)列的場(chǎng)景有很多,最常用的幾種,是做應(yīng)用程序松耦合、異步處理模式、發(fā)布與訂閱、最終一致性、錯(cuò)峰流控和日志緩沖等。
反之,如果需要強(qiáng)一致性,關(guān)注業(yè)務(wù)邏輯的處理結(jié)果,則使用 RPC 顯得更為合適。
異步處理
非核心流程異步化,減少系統(tǒng)響應(yīng)時(shí)間,提高吞吐量。例如:短信通知、終端狀態(tài)推送、App 推送、用戶注冊(cè)等。
消息隊(duì)列 一般都內(nèi)置了高效的通信機(jī)制,因此也可以用于單純的消息通訊,比如實(shí)現(xiàn)點(diǎn)對(duì)點(diǎn)消息隊(duì)列或者聊天室等。
應(yīng)用案例:網(wǎng)站用戶注冊(cè),注冊(cè)成功后會(huì)過(guò)一會(huì)發(fā)送郵件確認(rèn)或者短信。
系統(tǒng)解耦
系統(tǒng)之間不是強(qiáng)耦合的,消息接受者可以隨意增加,而不需要修改消息發(fā)送者的代碼。
消息發(fā)送者的成功不依賴消息接受者(比如:有些銀行接口不穩(wěn)定,但調(diào)用方并不需要依賴這些接口)。
不強(qiáng)依賴于非本系統(tǒng)的核心流程,對(duì)于非核心流程,可以放到消息隊(duì)列中讓消息消費(fèi)者去按需消費(fèi),而不影響核心主流程。
最終一致性
最終一致性不是消息隊(duì)列的必備特性,但確實(shí)可以依靠消息隊(duì)列來(lái)做最終一致性的事情:
先寫消息再操作,確保操作完成后再修改消息狀態(tài)。定時(shí)任務(wù)補(bǔ)償機(jī)制實(shí)現(xiàn)消息可靠發(fā)送接收、業(yè)務(wù)操作的可靠執(zhí)行,要注意消息重復(fù)與冪等設(shè)計(jì)。
所有不保證 100% 不丟消息的消息隊(duì)列,理論上無(wú)法實(shí)現(xiàn)最終一致性。
像 Kafka 一類的設(shè)計(jì),在設(shè)計(jì)層面上就有丟消息的可能(比如定時(shí)刷盤,如果掉電就會(huì)丟消息)。哪怕只丟千分之一的消息,業(yè)務(wù)也必須用其他的手段來(lái)保證結(jié)果正確。
廣播
生產(chǎn)者/消費(fèi)者模式,只需要關(guān)心消息是否送達(dá)隊(duì)列,至于誰(shuí)希望訂閱和需要消費(fèi),是下游的事情,無(wú)疑極大地減少了開(kāi)發(fā)和聯(lián)調(diào)的工作量。
流量削峰和流控
當(dāng)上下游系統(tǒng)處理能力存在差距的時(shí)候,利用消息隊(duì)列做一個(gè)通用的 “漏斗”,進(jìn)行限流控制。在下游有能力處理的時(shí)候,再進(jìn)行分發(fā)。
舉個(gè)例子:用戶在支付系統(tǒng)成功結(jié)賬后,訂單系統(tǒng)會(huì)通過(guò)短信系統(tǒng)向用戶推送扣費(fèi)通知。
短信系統(tǒng)可能由于短板效應(yīng),速度卡在網(wǎng)關(guān)上(每秒幾百次請(qǐng)求),跟前端的并發(fā)量不是一個(gè)數(shù)量級(jí)。于是,就造成支付系統(tǒng)和短信系統(tǒng)的處理能力出現(xiàn)差異化。
然而用戶晚上個(gè)半分鐘左右收到短信,一般是不會(huì)有太大問(wèn)題的。如果沒(méi)有消息隊(duì)列,兩個(gè)系統(tǒng)之間通過(guò)協(xié)商、滑動(dòng)窗口等復(fù)雜的方案也不是說(shuō)不能實(shí)現(xiàn)。
但系統(tǒng)復(fù)雜性指數(shù)級(jí)增長(zhǎng),勢(shì)必在上游或者下游做存儲(chǔ),并且要處理定時(shí)、擁塞等一系列問(wèn)題。
而且每當(dāng)有處理能力有差距的時(shí)候,都需要單獨(dú)開(kāi)發(fā)一套邏輯來(lái)維護(hù)這套邏輯。
所以,利用中間系統(tǒng)轉(zhuǎn)儲(chǔ)兩個(gè)系統(tǒng)的通信內(nèi)容,并在下游系統(tǒng)有能力處理這些消息的時(shí)候,再處理這些消息,是一套相對(duì)較通用的方式。
應(yīng)用案例:
日志處理
將消息隊(duì)列用在日志處理中,比如 Kafka 的應(yīng)用,解決海量日志傳輸和緩沖的問(wèn)題。
應(yīng)用案例:把日志進(jìn)行集中收集,用于計(jì)算 PV、用戶行為分析等等。
消息通訊
消息隊(duì)列一般都內(nèi)置了高效的通信機(jī)制,因此也可以用于單純的消息通訊,比如實(shí)現(xiàn)點(diǎn)對(duì)點(diǎn)消息隊(duì)列或者聊天室等。
消息隊(duì)列的推拉模型
Push 推消息模型
消息生產(chǎn)者將消息發(fā)送給消息隊(duì)列,消息隊(duì)列又將消息推給消息消費(fèi)者。
Pull 拉消息模型
消費(fèi)者請(qǐng)求消息隊(duì)列接受消息,消息生產(chǎn)者從消息隊(duì)列中拉該消息。
兩種類型的區(qū)別
兩種類型的區(qū)別如下圖:
消息隊(duì)列技術(shù)對(duì)比
本部分主要介紹四種常用的消息隊(duì)列( ActiveMQ/RabbitMQ/RocketMQ/Kafka)的主要特性、優(yōu)點(diǎn)、缺點(diǎn)。
ActiveMQ
ActiveMQ 是由 Apache 出品, ActiveMQ 是一個(gè)完全支持 JMS1.1 和 J2EE1.4 規(guī)范的 JMS Provider 實(shí)現(xiàn)。
它非常快速,支持多種語(yǔ)言的客戶端和協(xié)議,而且可以非常容易的嵌入到企業(yè)的應(yīng)用環(huán)境中,并有許多高級(jí)功能。
主要特性:
有很多種方法可以監(jiān)控 ActiveMQ 不同層面的數(shù)據(jù),包括使用在 JConsole 或者在 ActiveMQ 的 WebConsole 中使用 JMX。
通過(guò)處理 JMX 的告警消息,通過(guò)使用命令行腳本,甚至可以通過(guò)監(jiān)控各種類型的日志。
部署環(huán)境:ActiveMQ 可以運(yùn)行在 Java 語(yǔ)言所支持的平臺(tái)之上。
使用 ActiveMQ 需要:
優(yōu)點(diǎn)如下:
缺點(diǎn)如下:
RabbitMQ
RabbitMQ 于 2007 年發(fā)布,是一個(gè)在 AMQP(高級(jí)消息隊(duì)列協(xié)議)基礎(chǔ)上完成的,可復(fù)用的企業(yè)消息系統(tǒng),是當(dāng)前最主流的消息中間件之一。
主要特性如下:
使用 RabbitMQ 需要:
優(yōu)點(diǎn)如下:
缺點(diǎn)如下:
RocketMQ
RocketMQ 出自阿里的開(kāi)源產(chǎn)品,用 Java 語(yǔ)言實(shí)現(xiàn),在設(shè)計(jì)時(shí)參考了 Kafka,并做出了自己的一些改進(jìn),消息可靠性上比 Kafka 更好。
RocketMQ 在阿里內(nèi)部被廣泛應(yīng)用在訂單,交易,充值,流計(jì)算,消息推送,日志流式處理,Binglog 分發(fā)等場(chǎng)景。
主要特性如下:
部署環(huán)境:RocketMQ 可以運(yùn)行在 Java 語(yǔ)言所支持的平臺(tái)之上。
使用 RocketMQ 需要:
優(yōu)點(diǎn)如下:
缺點(diǎn)如下:
Kafka
Apache Kafka 是一個(gè)分布式消息發(fā)布訂閱系統(tǒng)。它最初由 LinkedIn 公司基于獨(dú)特的設(shè)計(jì)實(shí)現(xiàn)為一個(gè)分布式的日志提交系統(tǒng)(a distributed commit log),之后成為 Apache 項(xiàng)目的一部分。
Kafka 性能高效、可擴(kuò)展良好并且可持久化。它的分區(qū)特性,可復(fù)制和可容錯(cuò)都是不錯(cuò)的特性。
主要特性如下:
部署環(huán)境,使用 Kafka 需要:
優(yōu)點(diǎn)如下:
缺點(diǎn)如下:
幾種消息隊(duì)列對(duì)比
這里列舉了上述四種消息隊(duì)列的差異對(duì)比:
Kafka 在于分布式架構(gòu),RabbitMQ 基于 AMQP 協(xié)議來(lái)實(shí)現(xiàn),RocketMQ 的思路來(lái)源于 Kafka,改成了主從結(jié)構(gòu),在事務(wù)性和可靠性方面做了優(yōu)化。
廣泛來(lái)說(shuō),電商、金融等對(duì)事務(wù)一致性要求很高的,可以考慮 RabbitMQ 和 RocketMQ,對(duì)性能要求高的可考慮 Kafka。
小結(jié)
本文介紹了消息隊(duì)列的特點(diǎn),消息隊(duì)列的傳遞服務(wù)模型,消息的傳輸方式,消息的推拉模式。
然后介紹了 ActiveMQ,RabbitMQ,RocketMQ 和 Kafka 幾種常見(jiàn)的消息隊(duì)列,闡述了各種消息隊(duì)列的主要特點(diǎn)和優(yōu)缺點(diǎn)。
通過(guò)本文,對(duì)于消息隊(duì)列及相關(guān)技術(shù)選型,相信你會(huì)有更深入的理解和認(rèn)識(shí)。更多細(xì)節(jié)和原理性的東西,還需在實(shí)踐中見(jiàn)真知!
作者:陳林
簡(jiǎn)介:五年研發(fā)與架構(gòu)經(jīng)驗(yàn),曾任職 SAP 中國(guó)研發(fā)中心后端研發(fā)、上海冰鑒科技信息科技有限公司架構(gòu)師助理,目前擔(dān)任成都 ThoughtWorks 有限公司高級(jí)咨詢師與研發(fā)人員。熟悉大數(shù)據(jù)、高并發(fā)、負(fù)載均衡、緩存、數(shù)據(jù)庫(kù)、消息中間件、搜索引擎、容器和自動(dòng)化等領(lǐng)域。個(gè)人學(xué)習(xí)能力強(qiáng),技術(shù)熱情高,熱愛(ài)開(kāi)源和寫技術(shù)博客,善于溝通和分享。

我們?cè)谖⑿派?4小時(shí)期待你的聲音
解答本文疑問(wèn)/技術(shù)咨詢/運(yùn)營(yíng)咨詢/技術(shù)建議/互聯(lián)網(wǎng)交流