什么是消息隊列?

為什么要用消息隊列?
即,應用場景是什么,也就是用了有什么好處
解耦
多應用間通過消息隊列對同一消息進行處理,避免調用接口失敗導致整個過程失敗
異步
多應用對消息隊列中同一消息進行處理,應用間並發處理消息,相比串行處理,減少處理時間
削峰/限流
避免流量過大導致應用系統掛掉的情況
使用消息隊列需要注意什么?
系統復雜性增加
如何保證消息隊列是高可用,即做到集群高可用
如何保證消費的可靠性傳輸,即不丟消息
如何保證消息不被重復消費,即保證消費的冪等性
如何保證消息的順序性,即保證數據的邏輯正確性
簡單分析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
來源:簡書
著作權歸作者所有。商業轉載請聯系作者獲得授權,非商業轉載請注明出處。