淺談消息隊列之RocketMQ


什么是消息隊列?

 

 
 

為什么要用消息隊列?

   即,應用場景是什么,也就是用了有什么好處

    解耦

        多應用間通過消息隊列對同一消息進行處理,避免調用接口失敗導致整個過程失敗

    異步

        多應用對消息隊列中同一消息進行處理,應用間並發處理消息,相比串行處理,減少處理時間

    削峰/限流

        避免流量過大導致應用系統掛掉的情況

 


使用消息隊列需要注意什么?

系統復雜性增加

如何保證消息隊列是高可用,即做到集群高可用

如何保證消費的可靠性傳輸,即不丟消息

如何保證消息不被重復消費,即保證消費的冪等性

如何保證消息的順序性,即保證數據的邏輯正確性


簡單分析RocketMQ的原理

高可用

上架構

 
 

NameServer

維持心跳和提供Topic-Broker的關系數據,多個Namesrv之間相互沒有通信,單台Namesrv宕機不影響其他Namesrv與集群;即使整個Namesrv集群宕機,已經正常工作的Producer,Consumer,Broker仍然能正常工作,但新起的Producer, Consumer,Broker就無法工作,nameserver不會有頻繁的讀寫,所以性能開銷非常小,穩定性很高

Broker

Broker與Namesrv的心跳機制:單個Broker跟所有Namesrv保持心跳請求,心跳間隔為30秒,心跳請求中包括當前Broker所有的Topic信息

高可靠並發讀寫服務:所有發往broker的消息,有同步刷盤和異步刷盤機制,同步刷盤時,消息寫入物理文件才會返回成功,因此非常可靠;異步刷盤時,只有機器宕機,才會產生消息丟失,broker掛掉可能會發生,但是機器宕機崩潰是很少發生的,除非突然斷電。

負載均衡:Broker上存Topic信息,Topic由多個隊列組成,隊列會平均分散在多個Broker上,而Producer的發送機制保證消息盡量平均分布到所有隊列中,最終效果就是所有消息都平均落在每個Broker上

高可用:集群部署時一般都為主備,Broker名相同的一組Master/Slave Broker,其中包含一個Master Broker(Broker Id為0)和0~N個Slave Broker(Broker Id不為0),備機實時從主機同步消息,如果其中一個主機宕機,備機提供消費服務,但不提供寫服務。

Producer

Producer啟動時,也需要指定Namesrv的地址,從Namesrv集群中選一台Master建立長連接,生產者每30秒從Namesrv獲取Topic跟Broker的映射關系,更新到本地內存中。再跟Topic涉及的所有Broker建立長連接

生產者發送時,會自動輪詢當前所有可發送的broker,一條消息發送成功,下次換另外一個broker發送,以達到消息平均落到所有的broker上。假如某個Broker宕機,意味生產者最長需要30秒才能感知到。在這期間會向宕機的Broker發送消息。當一條消息發送到某個Broker失敗后,會往該broker自動再重發2次,假如還是發送失敗,則拋出發送失敗異常。業務捕獲異常,重新發送即可。客戶端里會自動輪詢另外一個Broker重新發送,這個對於用戶是透明的

消息發送方式分為,同步發送,異步發送,單向發送

Consumer

消費者啟動時需要指定Namesrv地址,與其中一個Namesrv建立長連接。消費者每隔30秒從nameserver獲取所有topic的最新隊列情況

 Consumer跟Broker是長連接,會每隔30秒發心跳信息到Broker。Broker端每10秒檢查一次當前存活的Consumer,若發現某個Consumer 2分鍾內沒有心跳,就斷開與該Consumer的連接,並且向該消費    組的其他實例發送通知,觸發該消費者集群的負載均衡。

消費者得到master宕機通知后,轉向slave消費(重定向,對於2次開發者透明),但是slave不能保證master的消息100%都同步過來了,因此會有少量的消息丟失。但是消息最終不會丟的,一旦master恢復,未同步過去的消息會被消費掉。

消費分為集群消費和廣播消費,


Topic+Queue :

topic的邏輯存儲模型:

 
 

如果各Master Broker有Slave Broker,Slave Broker中的結構和其對應的Master Broker完全相同。

Topic是邏輯概念,對於RocketMQ,一個Topic可以分布在各個Broker上,把一個Topic分布在一個Broker上的子集定義為一個Topic分片,其實就是在某一broke上一個topic的部分數據

Queue 存在的意義:每個Topic分片等分的Queue的數量可以不同,由用戶在創建Topic時指定, 是消費負載均衡過程中資源分配的基本單元.

Topic 的創建過程:

 
 

創建topic需要指定的參數,

    -b 指定broker上創建topic

    -c 指定cluster創建topic

-n 指定namesrv地址,cluster模式下必須從namesrv獲取broker地址,支持cluster模式下創建topic和支持broker模式下創建topic

    -t topic的名字標志

    -r/w 讀寫隊列的個數,建議相等

    -o 待研究不確定是不是保證全局有序消息的配置

 
 

存儲持久化

消息隊列的存儲選型:

分布式KV存儲,文件系統(目前業界較為常用的幾款產品RocketMQ/Kafka/RabbitMQ 均采用的是消息刷盤至所部署虛擬機/物理機的文件系統來做持久化,關系性DB(ActiveMQ)

從高可靠,高效率,中間件減少對第三方的依賴考慮, 文件系統>分布式KV存儲>關系型數據庫DB

存儲架構:

 
 

對比下Kafka的存儲結構:

 
 

 每個Topic有多個partition(queue),kafka的每個partition都是一個獨立的物理文件, 消息直接從里面讀寫

RocketMQ存儲的特點:

1.Broker單個實例下所有的隊列共用一個日志數據文件(即為CommitLog)來存儲

2.consumerQueue 是個消費的邏輯隊列,保存了數據在commit log中的offset

3. 消費讀取數據,需要先讀取consumerQueue,再讀取commit log,消息主體都是通過CommitLog來進行讀寫.

缺點:

1. 順序寫,隨即讀

克服缺點:

由於Consume Queue存儲數據量極少, 而且是順序讀, 在PAGECACHE預讀作用下, Consume Queue的讀性能幾乎與內存一致, 即使堆積情況下. 所以可認為Consume Queue完全不會阻礙讀性能

小結

RocketMQ可以嚴格的保證消息有序。但這個順序,不是全局順序,只是分區(queue)順序。要全局順序只能一個分區

RocketMQ不保證消息不重復,如果你的業務需要保證嚴格的不重復消息,需要你自己在業務端去重



作者:王洪倫
鏈接:https://www.jianshu.com/p/027accb2b7ae
來源:簡書
著作權歸作者所有。商業轉載請聯系作者獲得授權,非商業轉載請注明出處。


免責聲明!

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



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