設(shè)計概念
基于topic的發(fā)布/訂閱
其核心功能包括:
- 消息發(fā)送
- 消息存儲
- 消息消費(fèi)
設(shè)計目標(biāo)
- 架構(gòu)模式
與大部分消息中間件一樣讲冠,采用發(fā)布訂閱模式朽缴,基本參與組建:消息發(fā)送者,消息服務(wù)器(消息存儲)、消息消費(fèi)、路由發(fā)現(xiàn)聋亡。
- 順序消息
消息消費(fèi)者按照消息到達(dá)消息服務(wù)器的順序進(jìn)行消費(fèi)
- 消息過濾
消費(fèi)者可以對同一主題下按規(guī)則過濾- 消息在broker端過濾。broker只將消費(fèi)者過濾的消息發(fā)送給消費(fèi)者际乘。(tag)
- 消息在消息端過濾坡倔。缺點(diǎn)是,很多無用的消息會從broker端傳輸?shù)较M(fèi)端脖含。
- 消息存儲
核心罪塔。對消息存儲一版有兩個維度的考量- 消息堆積能力
- 消息存儲性能
-
消息高可用
通常影響消息可靠性的有以下幾種情況- broker正常關(guān)機(jī)
- broker異常crash
- os crash
- 機(jī)器斷電,但能立即恢復(fù)供電
- 機(jī)器無法開機(jī)(cpu养葵、主板征堪、內(nèi)存等關(guān)鍵設(shè)備損壞)
- 磁盤損壞
1-4:在同步刷盤機(jī)制下可以保證消息不丟失,在異步刷盤模式下关拒,會丟失少量请契。
5-6:屬于單點(diǎn)故障,一旦發(fā)生夏醉,該節(jié)點(diǎn)上的消息全部丟失。如果開啟了異步復(fù)制功能涌韩,大部分不丟失畔柔,只丟失少量。在雙寫機(jī)制下臣樱,可以保證消息不丟失靶擦。
- 消息到達(dá)(消息消費(fèi))低延遲
- 確保消息必須被消費(fèi)一次
通過消息消費(fèi)確認(rèn)ack機(jī)制來保證消息至少被消費(fèi)一次腮考。但由于ack有可能丟,所以會存在重復(fù)消費(fèi)的情況玄捕,這里就需要消費(fèi)者做冪等了踩蔚。
- 回溯消息
指消費(fèi)者已經(jīng)消費(fèi)成功的消息,由于業(yè)務(wù)要求需要重新消費(fèi)消息枚粘∠诿觯可以向前或向后。
- 消息堆積
消息中間件的主要功能是異步解耦馍迄。必須具備對前端的數(shù)據(jù)洪峰福也,提高后端系統(tǒng)的可用性,必然要求消息中間件具備一定的消息堆積能力攀圈。消息堆積能力依賴消息存儲暴凑。
- 定時消息
指消息發(fā)送到broker后,不能被消費(fèi)者立即消費(fèi)赘来,要到特定的時間點(diǎn)才能消費(fèi)现喳。
如果要支持任意精度的定時消息消費(fèi),必須在消息服務(wù)端對消息進(jìn)行排序犬辰,勢必會帶來很大的性能損耗嗦篱,故rocketMq不支持任意進(jìn)度的定時消息,而只支持特定延遲級別忧风。
- 消息重試機(jī)制
消費(fèi)機(jī)場默色,消息重新投遞。
流程
啟動時:
- nameServer 與 broker 建立長連接狮腿。把隊(duì)列路由信息維護(hù)到nameServer中腿宰。
- nameServer 與 producer 簡歷長連接。producer獲取自己要的topic下的隊(duì)列路由信息缘厢。
- nameServer 與 consumer 簡歷長連接吃度。根據(jù)group和topic,consumer找到自己對應(yīng)的queue贴硫。
發(fā)送消息的過程:
producer 發(fā)送消息給所有broker椿每。broker存到commitLog buffer中。
這里有個策略英遭,是同步刷臟頁還是異步刷臟頁间护。如果保證消息不丟失,就使用同步刷臟頁策略挖诸,消息落到commitlog后返回producer消息發(fā)送成功汁尺。如果消息發(fā)送異常,根據(jù)重試次數(shù)重試多律,直到成功痴突。這里保證了發(fā)送端的發(fā)送一定成功搂蜓。消息存到了commitLog,會把消息分發(fā)到consumerQueue和index索引文件中辽装。
分發(fā)到哪個隊(duì)列帮碰,也是有策略的:輪訓(xùn)、隨機(jī)拾积、key hash殉挽。因?yàn)槭锹淞舜疟P,所以消息存儲過程中殷勘,消息不會丟失此再。consumer從對應(yīng)的queue中根據(jù)offset拉取消息,消費(fèi)成功后玲销,返回ack输拇。標(biāo)識消費(fèi)成功。如果消費(fèi)失敗贤斜,不返回ack策吠,則broker端的offset不會變化,等consumer的下一次拉取瘩绒。
順序消息
兩種方式:
- 隊(duì)列大小猴抹,只開1個,那個消息只在一個隊(duì)列中锁荔,肯定是順序的蟀给。
- producer在調(diào)用send的時候,使用key hash來找queue阳堕,把key設(shè)置成一個跋理,則會被分發(fā)到同一個queue中,在同一個queue中恬总,消息也是順序的前普。