內容大綱:
RocketMQ一個(gè)純java、分布式、隊列模型的開(kāi)源消息中間件,前身是MetaQ,是阿里研發(fā)的一個(gè)隊列模型的消息中間件,后開(kāi)源給apache基金會(huì )成為了apache的頂級開(kāi)源項目,具有高性能、高可靠、高實(shí)時(shí)、分布式特點(diǎn)。
RocketMQ一共前后經(jīng)歷了三代演進(jìn):
1.第一代,推模式
數據存儲采用關(guān)系型數據庫,典型代表包括Notify、Napoli。
2.第二代,拉模式
自研的專(zhuān)有消息存儲,在日志處理方面參考Kafka,典型代表MetaQ。
3.第三代,以拉模式為主,兼有推模式
低延遲消息引擎RocketMQ,在二代功能特性的基礎上,為電商金融領(lǐng)域添加了可靠重試、基于文件存儲的分布式事務(wù)等特性。使用在了阿里大量的應用上,典型如雙11場(chǎng)景,具有萬(wàn)億級消息流轉。
1.RocketMQ的核心組件
RocketMQ主要由NameServer、Broker、Producer以及Consumer四部分構成。
1)NameServer:主要負責對于源數據的管理,包括了對于Topic和路由信息的管理。
NameServer是一個(gè)功能齊全的服務(wù)器,其角色類(lèi)似Dubbo中的Zookeeper,但NameServer與Zookeeper相比更輕量。主要是因為每個(gè)NameServer節點(diǎn)互相之間是獨立的,沒(méi)有任何信息交互。
備注:下面的消息類(lèi)型有Topic的介紹。
2) Producer
消息生產(chǎn)者,負責產(chǎn)生消息,一般由業(yè)務(wù)系統負責產(chǎn)生消息。
3 )Broker
消息中轉角色,負責存儲消息,轉發(fā)消息。
4)Consumer
消息消費者,負責消費消息,一般是后臺系統負責異步消費。
5)大致流程
Broker在啟動(dòng)的時(shí)候會(huì )去向NameServer注冊并且定時(shí)發(fā)送心跳,Producer在啟動(dòng)的時(shí)候會(huì )到NameServer上去拉取Topic所屬的Broker具體地址,然后向具體的Broker發(fā)送消息。具體如下圖:
2.RocketMQ的消息領(lǐng)域模型
主要分為Message、Topic、Queue、Offset以及Group這幾部分。

1)Topic
Topic表示消息的第一級類(lèi)型,比如一個(gè)電商系統的消息可以分為:交易消息、物流消息等。一條消息必須有一個(gè)Topic。
最細粒度的訂閱單位,一個(gè)Group可以訂閱多個(gè)Topic的消息。
2)Tag
Tag表示消息的第二級類(lèi)型,比如交易消息又可以分為:交易創(chuàng )建消息,交易完成消息等。RocketMQ提供2級消息分類(lèi),方便靈活控制。
3)Group
組,一個(gè)組可以訂閱多個(gè)Topic。
4)Message Queue
消息的物理管理單位。一個(gè)Topic下可以有多個(gè)Queue,Queue的引入使得消息的存儲可以分布式集群化,具有了水平擴展能力。
在 RocketMQ 中,所有消息隊列都是持久化,長(cháng)度無(wú)限的數據結構,所謂長(cháng)度無(wú)限是指隊列中的每個(gè)存儲單元都是定長(cháng),訪(fǎng)問(wèn)其中的存儲單元使用 Offset 來(lái)訪(fǎng)問(wèn),offset 為 java long 類(lèi)型,64 位,理論上在 100年內不會(huì )溢出,所以認為是長(cháng)度無(wú)限。
也可以認為 Message Queue 是一個(gè)長(cháng)度無(wú)限的數組,Offset 就是下標。
1.消息的順序
消息的順序指的是消息消費時(shí),能按照發(fā)送的順序來(lái)消費。例如:一個(gè)訂單產(chǎn)生了 3 條消息,分別是訂單創(chuàng )建、訂單付款、訂單完成。消費時(shí),要按照這個(gè)順序消費才有意義。但同時(shí)訂單之間又是可以并行消費的。
RocketMQ是通過(guò)將“相同ID的消息發(fā)送到同一個(gè)隊列,而一個(gè)隊列的消息只由一個(gè)消費者處理“來(lái)實(shí)現順序消息。如下圖:

這樣對于同一個(gè)訂單的創(chuàng )建、付款和完成消息,確保按照這一順序被發(fā)送和消費。
2.消息重復
1)消息重復的原因
消息領(lǐng)域有一個(gè)對消息投遞的QoS定義,分為:
QoS:Quality of Service,服務(wù)質(zhì)量
幾乎所有的MQ產(chǎn)品都聲稱(chēng)自己做到了At least once。既然是至少一次,那避免不了消息重復,尤其是在分布式網(wǎng)絡(luò )環(huán)境下。比如:網(wǎng)絡(luò )原因閃斷,ACK返回失敗等等故障,確認信息沒(méi)有傳送到消息隊列,導致消息隊列不知道自己已經(jīng)消費過(guò)該消息了,再次將該消息分發(fā)給其他的消費者。
不同的消息隊列發(fā)送的確認信息形式不同,例如RabbitMQ是發(fā)送一個(gè)ACK確認消息,RocketMQ是返回一個(gè)CONSUME_SUCCESS成功標志,kafka實(shí)際上有個(gè)offset的概念。
RocketMQ沒(méi)有內置消息去重的解決方案,最新版本是否支持還需確認。
2)消息去重
1)去重原則:使用業(yè)務(wù)端邏輯保持冪等性
冪等性:就是用戶(hù)對于同一操作發(fā)起的一次請求或者多次請求的結果是一致的,不會(huì )因為多次點(diǎn)擊而產(chǎn)生了副作用,數據庫的結果都是唯一的,不可變的。
只要保持冪等性,不管來(lái)多少條重復消息,最后處理的結果都一樣,需要業(yè)務(wù)端來(lái)實(shí)現。
2)去重策略:保證每條消息都有唯一編號(比如唯一流水號),且保證消息處理成功與去重表的日志同時(shí)出現。
建立一個(gè)消息表,拿到這個(gè)消息做數據庫的insert操作。給這個(gè)消息做一個(gè)唯一主鍵(primary key)或者唯一約束,那么就算出現重復消費的情況,就會(huì )導致主鍵沖突,那么就不再處理這條消息。
1.削峰填谷
比如如秒殺等大型活動(dòng)時(shí)會(huì )帶來(lái)較高的流量脈沖,如果沒(méi)做相應的保護,將導致系統超負荷甚至崩潰。如果因限制太過(guò)導致請求大量失敗而影響用戶(hù)體驗,可以利用MQ 超高性能的消息處理能力來(lái)解決。
2.異步解耦
通過(guò)上、下游業(yè)務(wù)系統的松耦合設計,比如:交易系統的下游子系統(如積分等)出現不可用甚至宕機,都不會(huì )影響到核心交易系統的正常運轉。
3.順序消息
與FIFO原理類(lèi)似,MQ提供的順序消息即保證消息的先進(jìn)先出,可以應用于交易系統中的訂單創(chuàng )建、支付、退款等流程。
4.分布式事務(wù)消息
比如阿里的交易系統、支付紅包等場(chǎng)景需要確保數據的最終一致性,需要引入 MQ 的分布式事務(wù),既實(shí)現了系統之間的解耦,又可以保證最終的數據一致性。
將大事務(wù)拆分成小事務(wù),減少系統間的交互,既高效又可靠。再利用MQ 的可靠傳輸與多副本技術(shù)確保消息不丟,At-Least-Once 特性來(lái)最終確保數據的最終一致性。
更多消息隊列MQ詳解,kafka可以參考:
阿里P8架構師談:分布式消息Kafka的原理、基礎架構、使用場(chǎng)景
以上就是RocketMQ的詳解,更多Redis、Spring Cloud、Dubbo、MySQL數等架構設計專(zhuān)題,具體請參考:

關(guān)注 轉發(fā)后,私信我關(guān)鍵詞 【高并發(fā)】即可獲??!

聯(lián)系客服