RocketMQ


應用場景

 
主要作用解耦、滑峰填谷
 
  1. 異構系統的整合,這個問題比較容易理解,在原阿里SOA ESB比較火的年代,很多異構系統需要進行互聯互通。
  2. 應用和應用之間的松耦合,這個在阿里巴巴內部很多的同步鏈路到異步鏈路里面,使用的非常多。
  3. 事件驅動機制和復雜事件架構模型里面的Backbone,底層的機制可以通過MQ來玩轉。
  4. 數據復制通道,這個有很多比較典型的應用場景,比如模擬MySQL的binlog解析,將數據的變更封裝為消息,進而復制到遠端的另外一個數據源。
  5. 與流計算引擎的整合,像和Apache Storm、Spark、Flink等框架進行整合,很好的服務於大數據通道。
 

思路總結

  1. 作為中國進入Apache極少量成員之一,其肯定是Niubility的,跟其他MQ一樣,用於解耦、削峰填谷
  2. 關鍵質量因素有:性能、可靠性、可排障性、順序、重復、事務性支持
  3. 整體設計上使用了常見的分布式設計方案,拆分成NameSvr(服務管理,如meta信息管理、ha管理等)、Broker(存儲)、Producer(消息生產者)、Comsumer(消息消費者)4個均可水平擴展的邏輯組件
  4. 在解決關鍵質量因素上,RocketMQ其核心模塊Broker Strore從Mysql innodb上借鑒了許多:
  • comsumerlog順序寫+queuelog索引表提高寫速度
  • comsumerlog存儲上使用定長(tag hash)
  • redolog提高寫能力
  • undolog解決事務問題
  • 定制索引樹(msgKey)
  • 零拷貝
5.在讀性能提速上,按官方文檔當前最高效的是使用批量,批量指在fetch msgs時,采用批量緩存至本地(默認1k),這樣能大大提高comsumerlog的單次轉盤查數據命中率。當然,當單條消息過大時,不建議拉取那么多緩存於本地,容易引起運行內存占用過多
6.在可靠性支持上,采取了雙向確認
7.在重復、順序問題上,采取了折中方案
8.在性能上,與大數據的寵兒kafka實驗室數據128kb以下消息,對比性能為15:20(w單位),略遜,主要由於為支持多topic擴展及可追蹤/事務特性(如多了msgKey索引樹)。從設計角度上看,合適是第一要義,15與20在w級別上,普通的業務項目來說,選擇rocketmq更為理智的選擇,你總不想在關鍵問題排障上,某個環節啞了。而在大數據對丟失排障幾近無訴求的情況下,用高吞吐的kafka更為合適。
9.看17年的成就上,有很多高級的CPU級別優化事項是我未清楚的高端優化。想起褚霸的文章提到“把軟件中相對成熟穩定的部分轉變為硬件進行固化,比如用MOC卡承載虛擬化引擎以及網絡和存儲offloading,帶來更高的性能和更低的成本”。Niubility
10.未來規划上,電商、金融已是阿里的2塊領地,metaq,notify對其訴求已覆蓋基本能力。開始向物聯網、大數據靠攏。如物聯網上,通過網關技術做協議Proxy。拭目以待
 

架構

 

領域模型

topic為邏輯概念,Queue為物理概念
 
tag: 標識某一類消息
 
msgKey:消息唯一標識,用於trace與冪等處理
 
 
 

邏輯架構

nameserver
 
producer
 
broker
 
consumer
 
 
 
上圖是一個典型的消息中間件收發消息的模型,RocketMQ也是這樣的設計,簡單說來,RocketMQ具有以下特點:
 
  • 是一個隊列模型的消息中間件,具有高性能、高可靠、高實時、分布式特點。
  • Producer、Consumer、隊列都可以分布式。
  • Producer向一些隊列輪流發送消息,隊列集合稱為Topic,Consumer如果做廣播消費,則一個consumer實例消費這個Topic對應的所有隊列,如果做集群消費,則多個Consumer實例平均消費這個topic對應的隊列集合。
  • 能夠保證嚴格的消息順序
  • 提供豐富的消息拉取模式
  • 高效的訂閱者水平擴展能力
  • 實時的消息訂閱機制
  • 億級消息堆積能力
  • 較少的依賴
 
 
 
集群消費模式:
廣播消費模式:
使用集群模式模擬廣播:
 
如果業務需要使用廣播模式,也可以創建多個 Consumer ID,用於訂閱同一個 Topic。
 
 
 
 
  • producer僅支持同集群提交,consumer支持跨集群消費
 
 
 

運行架構

 
下圖為RocketMQ服務端的整體架構設計。首先最上層是授權和認證部分,因為RocketMQ是基於TCP的自行研發的一套線路層協議
 
http://jaskey.github.io/blog/2016/12/19/rocketmq-network-protocol/),所以它需要編解碼以及序列化。再接下來可這一層是健康檢查,在健康檢查之后是流控和熔斷措施,因為再好的系統也需要流量保護,RocketMQ也是一樣,為了良好的可用性,RocketMQ提供了針對於不同維度的流量控制。再往下就是存儲,總體而言RocketMQ服務端對於部署運維是非常友好的,目前阿里巴巴內部也有很多系統在進行Docker容器化。
 
 
下面這幅圖展示的是SDK的架構圖。毋庸置疑第一步需要做的事情是服務發現,需要去找到發消息或者收消息具體的broker以及broker上的Topic,在此之外SDK還會需要做的事情就是長連接的保活。接下來與服務端相同,要有流量控制以及熔斷機制,另外為了保證實現高可用性,就需要提供補償機制,這種補償機制表現在發送端的Retry和接收端的Redelivery,也就是重投和重發。接下來,在SDK層還存在元信息通知更新消息,比如nameserver上數據變更就需要進行通知。
 
 

部署架構

如上圖所示, RocketMQ的部署結構有以下特點:
 
  • Name Server是一個幾乎無狀態節點,可集群部署,節點之間無任何信息同步。
  • Broker部署相對復雜,Broker分為Master與Slave,一個Master可以對應多個Slave,但是一個Slave只能對應一個Master,Master與Slave的對應關系通過指定相同的BrokerName,不同的BrokerId來定義,BrokerId為0表示Master,非0表示Slave。Master也可以部署多個。每個Broker與Name Server集群中的所有節點建立長連接,定時注冊Topic信息到所有Name Server。
  • Producer與Name Server集群中的其中一個節點(隨機選擇)建立長連接,定期從Name Server取Topic路由信息,並向提供Topic服務的Master建立長連接,且定時向Master發送心跳。Producer完全無狀態,可集群部署。
  • Consumer與Name Server集群中的其中一個節點(隨機選擇)建立長連接,定期從Name Server取Topic路由信息,並向提供Topic服務的Master、Slave建立長連接,且定時向Master、Slave發送心跳。Consumer既可以從Master訂閱消息,也可以從Slave訂閱消息,訂閱規則由Broker配置決定。
 

關鍵設計

 

消息存儲

consume queue與commit log

RocketMQ的消息存儲是由consume queue和commit log配合完成的。
consume queue是消息的邏輯隊列,相當於字典的目錄,用來指定消息在物理文件commit log上的位置。
Commit Log的消息是真實的消息數據,存儲單元長度不固定,文件順序寫,隨機讀。消息的存儲結構如下表所示,按照編號順序以及編號對應的內容依次存儲。
 
這種存儲設計,最大的好處是寫速度很快,多toipc共享順序寫commit log,又平衡了topic維度拆分的讀操作。
而讀性能優化方面,使用了二次查詢(topic queue log -> commit log)有所折損性能,使用了零拷貝、客戶端批量查(默認1k條消息)以提高轉盤命中率。
 
 
commitLog主要設計
以上是commit queue的主要字段,定長設計避免碎片化,定長設計上特別要說的是Tag使用了Hash code的設計,在需使用tag來get消息的場景下,可快速先過濾掉hashcode不匹配的消息(一層過濾大大減少了二次查詢的數據量),再通過commit log獲取到的完整tag進行精確匹配。
 

運維能力支持基礎--其他檢索方案

rocketMQ支持業務指定key(一般建議使用業務唯一ID)。

如果一個消息包含key值的話,會使用IndexFile存儲消息索引,這樣就很方便大家在MQ環節排障時,可以快速定位問題

文件的內容結構如圖:

Producer如何發送消息

 
Producer輪詢某topic下的所有隊列的方式來實現發送方的負載均衡,如下圖所示:

消息訂閱

 
RocketMQ消息訂閱有兩種模式,一種是Push模式,即MQServer主動向消費端推送;另外一種是Pull模式,即消費端在需要時,主動到MQServer拉取。但在具體實現時,Push和Pull模式都是采用消費端主動拉取的方式。
消費端的Push模式是通過長輪詢的模式來實現的,就如同下圖:

性能 

 
1、JSON序列化 2、IO mmap文件映射技術、PageCache、 清理文件、順序寫(單獨的線程專門做刷盤的操作) 3、Batch:Group Commit、Consumer
 
4、系統層面的高級優化:CPU的親和特性(線程/內存/網卡)、突破內存鎖限制,無鎖設計、NUMA架構Disable(如打開NUMA的交叉分配方案)、磁盤I/O調優-Deadline最后期限調度算法,避免I/O寫請求餓死情況出現
 

可靠性

 
 
文件存儲,多份備份
 
MQ 消息重試只針對集群消費方式生效;廣播方式不提供失敗重試特性,即消費失敗后,失敗消息不再重試,繼續消費新的消息
 
影響消息可靠性的幾種情況: 
 
  1. Broker正常關閉
  2. Broker異常Crash
  3. OS Crash
  4. 機器掉電,但是能立即恢復供電情況。
  5. 機器無法開機(可能是cpu、主板、內存等關鍵設備損壞)
  6. 磁盤設備損壞。
 
 
(1)、(2)、(3)、(4)四種情況都屬於硬件資源可立即恢復情況,RocketMQ在這四種情況下能保證消息不丟,或者丟失少量數據(依賴刷盤方式是同步還是異步)。 
 
(5)、(6)屬於單點故障,且無法恢復,一旦發生,在此單點上的消息全部丟失。RocketMQ在這兩種情況下,通過異步復制,可保證99%的消息不丟,但是仍然會有極少量的消息可能丟失。通過同步雙寫技術可以完全避免單點,同步雙寫勢必會影響性能,適合對消息可靠性要求極高的場合,例如與Money相關的應用。 
 
RocketMQ從3.0版本開始支持同步雙寫。

順序消息

 
方案一:嚴格順序消息
存在問題:1)並發量、阻塞  2)重復消息
 
事實上:
 
  1. 不關注亂序的應用實際大量存在
  2. 隊列無序並不意味着消息無序
 
方案二:從業務層面來保證消息的順序
 
RocketMQ通過輪詢所有隊列的方式來確定消息被發送到哪一個隊列(負載均衡策略)

消息重復

 
造成消息重復的根本原因是:網絡不可達。只要通過網絡交換數據,就無法避免這個問題。所以解決這個問題的辦法就是繞過這個問題。那么問題就變成了:如果消費端收到兩條一樣的消息,應該怎樣處理?
 
可選方案: 
 
  1. 消費端處理消息的業務邏輯保持冪等性
  2. MQ保證每條消息都有唯一編號且保證消息處理成功與去重表的日志同時出現
 
RocketMQ考慮分布式保障服務帶來對吞吐量影響,不支持消息重復處理
 

事務消息

1、消息發送方:RocketMQ第一階段發送Prepared消息時,會拿到消息的地址,第二階段執行本地事物,第三階段通過第一階段拿到的地址去訪問消息,並修改消息的狀態。
 
細RocketMQ會定期掃描消息集群中的事物消息,如果發現了Prepared消息,它會向消息發送端(生產者)確認,Bob的錢到底是減了還是沒減呢?如果減了是回滾還是繼續發送確認消息呢?RocketMQ會根據發送端設置的策略來決定是回滾還是繼續發送確認消息。這樣就保證了消息發送與本地事務同時成功或同時失敗。
 
2、消費方:Smith端開始消費這條消息,這個時候就會出現消費失敗和消費超時兩個問題
 
   1)解決超時問題的思路就是一直重試,直到消費端消費消息成功,整個過程中有可能會出現消息重復的問題,按照前面的思路解決即可
 
   2)消費端超時問題,但是如果消費失敗怎么辦?解決方法是:低概率問題,人工解決
 
 
 

業界標桿對比

 
Kafka最初被設計用來做日志處理,是一個不折不扣的大數據通道,追求高吞吐,存在丟消息的可能。其背后的研發團隊也圍繞着Kafka進行了商業包裝,目前在一些中小型公司被廣泛使用,國內也有不少忠實的擁捧着。
 
RocketMQ天生為金融互聯網領域而生,追求高可靠、高可用、高並發、低延遲,是一個阿里巴巴由內而外成功孕育的典范,除了阿里集團上千個應用外,不完全統計,國內至少有上百家單位、科研教育機構在使用。關於這幾個MQ產品更詳細的特性對比:

未來展望

 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM