一篇文章詳解RocketMQ消息中間件
消息中間件在高并發(fā)的業(yè)務(wù)場(chǎng)景占據(jù)了非常重要的位置,其中國(guó)內(nèi)的典型代表Java實(shí)現(xiàn)的RocketMQ需要重點(diǎn)掌握。
本文重點(diǎn)詳解如下5點(diǎn):
1.RocketMQ的介紹
2.RocketMQ的技術(shù)演進(jìn)
3.RocketMQ的架構(gòu)設(shè)計(jì)
4.RocketMQ的核心特性
5.RocketMQ的應(yīng)用場(chǎng)景
RocketMQ的簡(jiǎn)介
RocketMQ一個(gè)純java、分布式、隊(duì)列模型的開(kāi)源消息中間件,前身是MetaQ,是阿里研發(fā)的一個(gè)隊(duì)列模型的消息中間件,后開(kāi)源給apache基金會(huì)成為了apache的頂級(jí)開(kāi)源項(xiàng)目,具有高性能、高可靠、高實(shí)時(shí)、分布式特點(diǎn)。
RocketMQ的演進(jìn)
RocketMQ一共前后經(jīng)歷了三代演進(jìn):
1.第一代,推模式
數(shù)據(jù)存儲(chǔ)采用關(guān)系型數(shù)據(jù)庫(kù),典型代表包括Notify、Napoli。
2.第二代,拉模式
自研的專(zhuān)有消息存儲(chǔ),在日志處理方面參考Kafka,典型代表MetaQ。
3.第三代,以拉模式為主,兼有推模式
低延遲消息引擎RocketMQ,在二代功能特性的基礎(chǔ)上,為電商金融領(lǐng)域添加了可靠重試、基于文件存儲(chǔ)的分布式事務(wù)等特性。使用在了阿里大量的應(yīng)用上,典型如雙11場(chǎng)景,具有萬(wàn)億級(jí)消息流轉(zhuǎn)。
RocketMQ的架構(gòu)設(shè)計(jì)
1.RocketMQ的核心組件
RocketMQ主要由NameServer、Broker、Producer以及Consumer四部分構(gòu)成。
1)NameServer:
主要負(fù)責(zé)對(duì)于源數(shù)據(jù)的管理,包括了對(duì)于Topic和路由信息的管理。
NameServer是一個(gè)功能齊全的服務(wù)器,其角色類(lèi)似Dubbo中的Zookeeper,但NameServer與Zookeeper相比更輕量。主要是因?yàn)槊總€(gè)NameServer節(jié)點(diǎn)互相之間是獨(dú)立的,沒(méi)有任何信息交互。
備注:下面的消息類(lèi)型有Topic的介紹。
2) Producer
消息生產(chǎn)者,負(fù)責(zé)產(chǎn)生消息,一般由業(yè)務(wù)系統(tǒng)負(fù)責(zé)產(chǎn)生消息。
- Producer由用戶進(jìn)行分布式部署,消息由Producer通過(guò)多種負(fù)載均衡模式發(fā)送到Broker集群,發(fā)送低延時(shí),支持快速失敗。
3 )Broker
消息中轉(zhuǎn)角色,負(fù)責(zé)存儲(chǔ)消息,轉(zhuǎn)發(fā)消息。
- Broker是具體提供業(yè)務(wù)的服務(wù)器,單個(gè)Broker節(jié)點(diǎn)與所有的NameServer節(jié)點(diǎn)保持長(zhǎng)連接及心跳,并會(huì)定時(shí)將Topic信息注冊(cè)到NameServer,順帶一提底層的通信和連接都是基于Netty實(shí)現(xiàn)的。
- Broker負(fù)責(zé)消息存儲(chǔ),以Topic為緯度支持輕量級(jí)的隊(duì)列,單機(jī)可以支撐上萬(wàn)隊(duì)列規(guī)模,支持消息推拉模型。
- 官網(wǎng)上有數(shù)據(jù)顯示:具有上億級(jí)消息堆積能力,同時(shí)可嚴(yán)格保證消息的有序性。
4)Consumer
消息消費(fèi)者,負(fù)責(zé)消費(fèi)消息,一般是后臺(tái)系統(tǒng)負(fù)責(zé)異步消費(fèi)。
- Consumer也由用戶部署,支持PUSH和PULL兩種消費(fèi)模式,支持集群消費(fèi)和廣播消息,提供實(shí)時(shí)的消息訂閱機(jī)制。
5)大致流程
- Broker在啟動(dòng)的時(shí)候會(huì)去向NameServer注冊(cè)并且定時(shí)發(fā)送心跳,Producer在啟動(dòng)的時(shí)候會(huì)到NameServer上去拉取Topic所屬的Broker具體地址,然后向具體的Broker發(fā)送消息。具體如下圖:
2.RocketMQ的消息領(lǐng)域模型
主要分為Message、Topic、Queue、Offset以及Group這幾部分。
1)Topic
Topic表示消息的第一級(jí)類(lèi)型,比如一個(gè)電商系統(tǒng)的消息可以分為:交易消息、物流消息等。一條消息必須有一個(gè)Topic。
最細(xì)粒度的訂閱單位,一個(gè)Group可以訂閱多個(gè)Topic的消息。
2)Tag
Tag表示消息的第二級(jí)類(lèi)型,比如交易消息又可以分為:交易創(chuàng)建消息,交易完成消息等。RocketMQ提供2級(jí)消息分類(lèi),方便靈活控制。
3)Group
組,一個(gè)組可以訂閱多個(gè)Topic。
4)Message Queue
消息的物理管理單位。一個(gè)Topic下可以有多個(gè)Queue,Queue的引入使得消息的存儲(chǔ)可以分布式集群化,具有了水平擴(kuò)展能力。
在RocketMQ 中,所有消息隊(duì)列都是持久化,長(zhǎng)度無(wú)限的數(shù)據(jù)結(jié)構(gòu),所謂長(zhǎng)度無(wú)限是指隊(duì)列中的每個(gè)存儲(chǔ)單元都是定長(zhǎng),訪問(wèn)其中的存儲(chǔ)單元使用
Offset 來(lái)訪問(wèn),offset 為 java long 類(lèi)型,64 位,理論上在 100年內(nèi)不會(huì)溢出,所以認(rèn)為是長(zhǎng)度無(wú)限。
也可以認(rèn)為 Message Queue 是一個(gè)長(zhǎng)度無(wú)限的數(shù)組,Offset 就是下標(biāo)。
RocketMQ的關(guān)鍵特性
1.消息的順序
消息的順序指的是消息消費(fèi)時(shí),能按照發(fā)送的順序來(lái)消費(fèi)。例如:一個(gè)訂單產(chǎn)生了 3 條消息,分別是訂單創(chuàng)建、訂單付款、訂單完成。消費(fèi)時(shí),要按照這個(gè)順序消費(fèi)才有意義。但同時(shí)訂單之間又是可以并行消費(fèi)的。
RocketMQ是通過(guò)將“相同ID的消息發(fā)送到同一個(gè)隊(duì)列,而一個(gè)隊(duì)列的消息只由一個(gè)消費(fèi)者處理“來(lái)實(shí)現(xiàn)順序消息。如下圖:
這樣對(duì)于同一個(gè)訂單的創(chuàng)建、付款和完成消息,確保按照這一順序被發(fā)送和消費(fèi)。
2.消息重復(fù)
1)消息重復(fù)的原因
消息領(lǐng)域有一個(gè)對(duì)消息投遞的QoS定義,分為:
- 最多一次(At most once)
- 至少一次(At least once)
- 僅一次( Exactly once)
QoS:Quality of Service,服務(wù)質(zhì)量
幾乎所有的MQ產(chǎn)品都聲稱(chēng)自己做到了At least once。既然是至少一次,那避免不了消息重復(fù),尤其是在分布式網(wǎng)絡(luò)環(huán)境下。比如:網(wǎng)絡(luò)原因閃斷,ACK返回失敗等等故障,確認(rèn)信息沒(méi)有傳送到消息隊(duì)列,導(dǎo)致消息隊(duì)列不知道自己已經(jīng)消費(fèi)過(guò)該消息了,再次將該消息分發(fā)給其他的消費(fèi)者。
不同的消息隊(duì)列發(fā)送的確認(rèn)信息形式不同,例如RabbitMQ是發(fā)送一個(gè)ACK確認(rèn)消息,RocketMQ是返回一個(gè)CONSUME_SUCCESS成功標(biāo)志,kafka實(shí)際上有個(gè)offset的概念。
RocketMQ沒(méi)有內(nèi)置消息去重的解決方案,最新版本是否支持還需確認(rèn)。
2)消息去重
a.去重原則:使用業(yè)務(wù)端邏輯保持冪等性
冪等性:就是用戶對(duì)于同一操作發(fā)起的一次請(qǐng)求或者多次請(qǐng)求的結(jié)果是一致的,不會(huì)因?yàn)槎啻吸c(diǎn)擊而產(chǎn)生了副作用,數(shù)據(jù)庫(kù)的結(jié)果都是唯一的,不可變的。
只要保持冪等性,不管來(lái)多少條重復(fù)消息,最后處理的結(jié)果都一樣,需要業(yè)務(wù)端來(lái)實(shí)現(xiàn)。
b.去重策略:保證每條消息都有唯一編號(hào)(比如唯一流水號(hào)),且保證消息處理成功與去重表的日志同時(shí)出現(xiàn)。
建立一個(gè)消息表,拿到這個(gè)消息做數(shù)據(jù)庫(kù)的insert操作。給這個(gè)消息做一個(gè)唯一主鍵(primary key)或者唯一約束,那么就算出現(xiàn)重復(fù)消費(fèi)的情況,就會(huì)導(dǎo)致主鍵沖突,那么就不再處理這條消息。
RocketMQ的應(yīng)用場(chǎng)景
1.削峰填谷
比如如秒殺等大型活動(dòng)時(shí)會(huì)帶來(lái)較高的流量脈沖,如果沒(méi)做相應(yīng)的保護(hù),將導(dǎo)致系統(tǒng)超負(fù)荷甚至崩潰。如果因限制太過(guò)導(dǎo)致請(qǐng)求大量失敗而影響用戶體驗(yàn),可以利用MQ 超高性能的消息處理能力來(lái)解決。
2.異步解耦
通過(guò)上、下游業(yè)務(wù)系統(tǒng)的松耦合設(shè)計(jì),比如:交易系統(tǒng)的下游子系統(tǒng)(如積分等)出現(xiàn)不可用甚至宕機(jī),都不會(huì)影響到核心交易系統(tǒng)的正常運(yùn)轉(zhuǎn)。
3.順序消息
與FIFO原理類(lèi)似,MQ提供的順序消息即保證消息的先進(jìn)先出,可以應(yīng)用于交易系統(tǒng)中的訂單創(chuàng)建、支付、退款等流程。
4.分布式事務(wù)消息
比如阿里的交易系統(tǒng)、支付紅包等場(chǎng)景需要確保數(shù)據(jù)的最終一致性,需要引入 MQ 的分布式事務(wù),既實(shí)現(xiàn)了系統(tǒng)之間的解耦,又可以保證最終的數(shù)據(jù)一致性。
將大事務(wù)拆分成小事務(wù),減少系統(tǒng)間的交互,既高效又可靠。再利用MQ 的可靠傳輸與多副本技術(shù)確保消息不丟,At-Least-Once 特性來(lái)最終確保數(shù)據(jù)的最終一致性。