RocketMQ概念篇

導(dǎo)讀

白話系列文章講述RocketMQ。因?yàn)槭前自?,盡量通過(guò)比較直白的方式來(lái)介紹RocketMQ,所以涉及到詳細(xì)的技術(shù)細(xì)節(jié)可能表述的不是那么嚴(yán)謹(jǐn)。但是不用擔(dān)心,后續(xù)會(huì)有專門(mén)的文章詳細(xì)介紹技術(shù)細(xì)節(jié)。

這篇文章介紹的是RocketMQ基本概念,分為介紹和提問(wèn)兩部分,如果對(duì)概念很清楚了就不用了,閑暇無(wú)事可以看看提問(wèn)。

類似介紹概念的文章網(wǎng)上比較多,希望這篇文章提問(wèn)式的閱讀會(huì)讓大家對(duì)概念能有更清晰的認(rèn)識(shí)。



MQ

Message Queue消息隊(duì)列,既然是隊(duì)列,就要實(shí)現(xiàn)數(shù)據(jù)結(jié)構(gòu)中隊(duì)列的基本特征,比如先進(jìn)先出,入隊(duì)、出隊(duì)操作等。

RocketMQ就是把內(nèi)存中使用的那個(gè)隊(duì)列,變成一個(gè)獨(dú)立的、大家都可以用的隊(duì)列系統(tǒng)。



Topic

一個(gè)業(yè)務(wù)事件,是整個(gè)MQ領(lǐng)域最核心的概念,無(wú)論是生產(chǎn)還是消費(fèi)都是針對(duì)Topic進(jìn)行操作。

如果MQ是個(gè)大的隊(duì)列,只有一個(gè)隊(duì)列可以用太浪費(fèi)了吧,來(lái)分一分分一分,分解成很多個(gè)小的獨(dú)立的隊(duì)列。RocketMQ變成一個(gè)管理隊(duì)列的系統(tǒng),而分解下來(lái)的若干個(gè)小的隊(duì)列通過(guò)什么來(lái)區(qū)分呢?

就是通過(guò)topic。

比如我的業(yè)務(wù)定義topic:tp_im_event。你的業(yè)務(wù)定義topic:tp_cargo_event,那就是兩個(gè)小隊(duì)列了,我的業(yè)務(wù)用我的隊(duì)列,你的項(xiàng)目用你的隊(duì)列。Topic就是隊(duì)列的名字

提問(wèn)

如果不小心定義了相同的Topic名字,上線后會(huì)發(fā)生什么?

申請(qǐng)Topic好麻煩,所有業(yè)務(wù)都用一個(gè)Topic好了,這樣會(huì)有什么問(wèn)題?

Topic名字起的越酷炫越好?



Queue

既然Topic是隊(duì)列的名字,那么queue就表示真實(shí)操作的隊(duì)列了。一開(kāi)始的時(shí)候一個(gè)Topic就對(duì)應(yīng)一個(gè)queue,多好,一個(gè)是名字、一個(gè)是現(xiàn)實(shí)。可是用著用著就悲催了,為啥?消息操作太多了,全都懟在一個(gè)小隊(duì)列上。為了提高效率,咋整??RocketMQ是這樣做的,一個(gè)Topic綁定的是一組queue,這樣每個(gè)queue分?jǐn)偛糠謮毫Γ阅芫蜕先チ恕?/p>

讀隊(duì)列個(gè)數(shù):可以用來(lái)讀取數(shù)據(jù)的隊(duì)列個(gè)數(shù)

寫(xiě)隊(duì)列個(gè)數(shù):可以用來(lái)寫(xiě)入數(shù)據(jù)的隊(duì)列個(gè)數(shù)

queue:真實(shí)存儲(chǔ)數(shù)據(jù)用的隊(duì)列。

提問(wèn)

我申請(qǐng)了一個(gè)Topic,讀隊(duì)列設(shè)置2,寫(xiě)隊(duì)列設(shè)置4有什么問(wèn)題么?

我申請(qǐng)了一個(gè)Topic,讀隊(duì)列設(shè)置4,寫(xiě)隊(duì)列設(shè)置2有什么問(wèn)題么?

既然增加隊(duì)列數(shù)可以提升性能,我申請(qǐng)8848個(gè)隊(duì)列的Topic是不是可以達(dá)到性能的巔峰?



Message

好了,說(shuō)完了隊(duì)列,我們?cè)賮?lái)說(shuō)一說(shuō)隊(duì)列存儲(chǔ)的內(nèi)容是什么?

存儲(chǔ)的是消息!Message!盡量小,別發(fā)個(gè)文件啊什么的大東西,后面真心扛不?。ǔ^(guò)特定大小還會(huì)報(bào)錯(cuò))



Tag

一個(gè)queue里都是消息,如何對(duì)這些消息進(jìn)行歸類呢?為了進(jìn)一步細(xì)化消息,有了Tag的概念??梢酝ㄟ^(guò)Tag對(duì)相同消息進(jìn)行歸類,這樣用戶就可以只訂閱一部分的消息了(只訂閱部分Tag)

比如:有一個(gè)Topic叫做‘發(fā)貨’,下游消費(fèi)者希望可以根據(jù)貨源進(jìn)行不同的處理,可以通過(guò)‘tag=北京’以及‘tag=上?!瘉?lái)區(qū)分不同的發(fā)貨源。下游消費(fèi)者,可以單獨(dú)訂閱‘上?!呢浳铮蛘摺畉ag=上海|江蘇|浙江’來(lái)訂閱這三個(gè)地區(qū)的貨物,還可以‘tag=*’來(lái)訂閱全國(guó)的貨物。




Key

發(fā)送了某個(gè)消息,但是希望在后臺(tái)很方便的搜索到,就要通過(guò)key了??梢愿鶕?jù)key搜索到所有相關(guān)的Message。可以認(rèn)為RocketMQ內(nèi)部維護(hù)了一個(gè)非常大的HashMap,key就是這個(gè)key,value就是Message,如果出現(xiàn)Hash沖突就用鏈表來(lái)報(bào)錯(cuò)對(duì)應(yīng)關(guān)系。

提問(wèn)

每次申請(qǐng)Topic好煩啊,索性申請(qǐng)個(gè)叫tp_all的topic算了,然后內(nèi)部用tag來(lái)區(qū)分豈不是美滋滋,這樣很好吧?

我是生產(chǎn)者,我可以任意修改發(fā)送的消息體?

一個(gè)topic里面有什么tag我又不知道,索性消費(fèi)所有消息,內(nèi)部判斷是不是我要的消息內(nèi)容不就好?



Producer

生產(chǎn)者:針對(duì)某一個(gè)Topic制造數(shù)據(jù),把數(shù)據(jù)塞到queue里。

簡(jiǎn)單點(diǎn):發(fā)消息的

Producer Group

管理消息的時(shí)候,我們肯定會(huì)遇見(jiàn)這個(gè)問(wèn)題,某個(gè)消息誰(shuí)發(fā)的?RocketMQ把發(fā)送者的身份抽象成了Producer Group,就是[發(fā)送組]。

簡(jiǎn)單點(diǎn):這個(gè)東西命名成項(xiàng)目名就行,相同Producer Group保持相同業(yè)務(wù)行為

提問(wèn)

我的項(xiàng)目要發(fā)送10個(gè)Topic,定義相同的Producer Group可以么?

有一個(gè)Topic,可以多個(gè)Producer Group一起生產(chǎn)么?

2臺(tái)機(jī)器有相同的Producer Group,機(jī)器1發(fā)送tp1、 機(jī)器2發(fā)送tp2這樣有問(wèn)題么?

一個(gè)Topic有Producer Group:‘test_group’ 兩個(gè)項(xiàng)目都用了,但是A項(xiàng)目發(fā)送的tag叫A,B項(xiàng)目發(fā)送的消息Tag是B,請(qǐng)問(wèn)有問(wèn)題么??


Consumer

消費(fèi)者:把queue里面的消息拿出來(lái)用

消費(fèi)行為:如何處理通過(guò)Topic+Tag定位的消息

Consumer Group

重點(diǎn)!重點(diǎn)!重點(diǎn)!來(lái)了,直接翻譯是‘消費(fèi)組’

一個(gè)RocketMQ集群是如何區(qū)分消費(fèi)者是誰(shuí)的呢?就是通過(guò)消費(fèi)組,相同消費(fèi)組的機(jī)器,MQ認(rèn)為消費(fèi)行為是一致的。業(yè)務(wù)上一定要保證相同消費(fèi)組有相同的消費(fèi)行為。對(duì)于不同的消費(fèi)組名字,RocketMQ就認(rèn)為是個(gè)不同消費(fèi)者了。如果修改了消費(fèi)組的名字,那就是新的消費(fèi)者,就會(huì)按照新的消費(fèi)組的消費(fèi)進(jìn)度處理消費(fèi)。

? ? 消息那么多,項(xiàng)目都重啟無(wú)數(shù)次了,RocketMQ是如何記錄消息消費(fèi)到什么地方了呢?

? ? 也是通過(guò)消費(fèi)組,RocketMQ內(nèi)部會(huì)維護(hù)一個(gè)關(guān)系,記錄Consumer Group和消費(fèi)進(jìn)度之間的聯(lián)系。所以,如果把Consumer Group的名字改掉是可能重新消費(fèi)之前的所有數(shù)據(jù)的(視初始消費(fèi)位置而定)

提問(wèn)

兩個(gè)服務(wù),服務(wù)A和服務(wù)B,消費(fèi)相同集群的相同Topic,既然服務(wù)不一樣,那么就算是定義了相同的consumer group也無(wú)所謂吧?

常見(jiàn)問(wèn)題:消費(fèi)組名字命名的不合理,上線后悄悄改回來(lái)行不行?

不小心用了別人的消費(fèi)組名,悄悄改回來(lái)重新上線也沒(méi)什么問(wèn)題吧?

常見(jiàn)問(wèn)題:一個(gè)服務(wù)有消費(fèi)組A消費(fèi)3個(gè)Topic,有一次上線,希望消費(fèi)4個(gè)Topic。對(duì)于新消費(fèi)的消息希望可以灰度驗(yàn)證一段時(shí)間。請(qǐng)問(wèn)有問(wèn)題么?


消息延遲/積壓

消息隊(duì)列主要的功能是模塊結(jié)偶,同步轉(zhuǎn)異步和削峰,必然會(huì)出現(xiàn)生產(chǎn)非常快但是消費(fèi)慢這種事情,比如生產(chǎn)的速度是100000/s但是消費(fèi)速度是1/s,這個(gè)時(shí)候就叫做消息積壓或者消費(fèi)延遲(Delay)。理論上RockeMQ對(duì)于這種場(chǎng)景有比較好的適應(yīng)能力,原理大致這樣:正常的生產(chǎn)消費(fèi)都是操作內(nèi)存數(shù)據(jù),所以比較快。但是如果積壓非常多,內(nèi)存明顯扛不住了,則降級(jí)為生產(chǎn)消費(fèi)的是磁盤(pán)數(shù)據(jù),直接操作磁盤(pán)。磁盤(pán)肯定比內(nèi)存的速度慢很多啦。

這個(gè)時(shí)候整個(gè)集群的處理能力就拉低了。所以最好生產(chǎn)和消費(fèi)能力不要相差太多,即便相差很多,積壓也應(yīng)該在有限的時(shí)間內(nèi)處理完畢。

目前比較容易出現(xiàn)消息積壓的情況有:

1.新消費(fèi)組上線(消費(fèi)歷史消息)

2.消費(fèi)能力弱

3.生產(chǎn)洪峰(比如for循環(huán)發(fā)消息,job發(fā)消息)

由于RocketMQ開(kāi)源版本沒(méi)有多租戶隔離,所以公共集群使用的過(guò)程中會(huì)有相互影響發(fā)生,鑒于此大家在上線前還是要合理評(píng)估自己的系統(tǒng)能力。

提問(wèn)

消費(fèi)延遲太多了,業(yè)務(wù)上接受丟棄一部分消息,如何操作呢?

消息的處理線程太少了,想加大處理線程怎么辦?

自己搞個(gè)線程池處理消息是不是很贊?


InstanceName

這個(gè)概念比較尷尬。上面說(shuō)的Producer Group和Consumer Group都是邏輯概念。如果需要連接多集群,就需要物理上進(jìn)行區(qū)分(Instance Name)。

一個(gè)Instance Name對(duì)應(yīng)一個(gè)連接,默認(rèn)的值是本機(jī)ip@進(jìn)程號(hào)。連接多集群的時(shí)候務(wù)必修改這個(gè)值。

提問(wèn)

要向兩個(gè)RocketMQ集群生產(chǎn)數(shù)據(jù),只需要設(shè)置不同的Producer Group即可?

要從兩個(gè)RocketMQ集群消費(fèi)數(shù)據(jù),只需要設(shè)置不同的Consumer Group即可?

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容