導(dǎo)讀
白話系列文章講述RocketMQ注服。因?yàn)槭前自捦锇遥M量通過比較直白的方式來介紹RocketMQ,所以涉及到詳細(xì)的技術(shù)細(xì)節(jié)可能表述的不是那么嚴(yán)謹(jǐn)浇揩。但是不用擔(dān)心仪壮,后續(xù)會(huì)有專門的文章詳細(xì)介紹技術(shù)細(xì)節(jié)。
這篇文章介紹的是RocketMQ基本概念胳徽,分為介紹和提問兩部分积锅,如果對(duì)概念很清楚了就不用了,閑暇無事可以看看提問养盗。
類似介紹概念的文章網(wǎng)上比較多缚陷,希望這篇文章提問式的閱讀會(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)域最核心的概念柄慰,無論是生產(chǎn)還是消費(fèi)都是針對(duì)Topic進(jìn)行操作鳍悠。
如果MQ是個(gè)大的隊(duì)列,只有一個(gè)隊(duì)列可以用太浪費(fèi)了吧坐搔,來分一分分一分藏研,分解成很多個(gè)小的獨(dú)立的隊(duì)列。RocketMQ變成一個(gè)管理隊(duì)列的系統(tǒng)概行,而分解下來的若干個(gè)小的隊(duì)列通過什么來區(qū)分呢蠢挡?
就是通過topic。
比如我的業(yè)務(wù)定義topic:tp_im_event凳忙。你的業(yè)務(wù)定義topic:tp_cargo_event业踏,那就是兩個(gè)小隊(duì)列了,我的業(yè)務(wù)用我的隊(duì)列涧卵,你的項(xiàng)目用你的隊(duì)列勤家。Topic就是隊(duì)列的名字。
提問:
如果不小心定義了相同的Topic名字柳恐,上線后會(huì)發(fā)生什么伐脖?
申請(qǐng)Topic好麻煩,所有業(yè)務(wù)都用一個(gè)Topic好了胎撤,這樣會(huì)有什么問題晓殊?
Topic名字起的越酷炫越好?
Queue
既然Topic是隊(duì)列的名字伤提,那么queue就表示真實(shí)操作的隊(duì)列了。一開始的時(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ù):可以用來讀取數(shù)據(jù)的隊(duì)列個(gè)數(shù)
寫隊(duì)列個(gè)數(shù):可以用來寫入數(shù)據(jù)的隊(duì)列個(gè)數(shù)
queue:真實(shí)存儲(chǔ)數(shù)據(jù)用的隊(duì)列靶溜。
提問:
我申請(qǐng)了一個(gè)Topic开瞭,讀隊(duì)列設(shè)置2懒震,寫隊(duì)列設(shè)置4有什么問題么?
我申請(qǐng)了一個(gè)Topic嗤详,讀隊(duì)列設(shè)置4个扰,寫隊(duì)列設(shè)置2有什么問題么?
既然增加隊(duì)列數(shù)可以提升性能葱色,我申請(qǐng)8848個(gè)隊(duì)列的Topic是不是可以達(dá)到性能的巔峰递宅?
Message
好了,說完了隊(duì)列冬筒,我們?cè)賮碚f一說隊(duì)列存儲(chǔ)的內(nèi)容是什么?
存儲(chǔ)的是消息恐锣!Message!盡量小舞痰,別發(fā)個(gè)文件啊什么的大東西土榴,后面真心扛不住(超過特定大小還會(huì)報(bào)錯(cuò))
Tag
一個(gè)queue里都是消息响牛,如何對(duì)這些消息進(jìn)行歸類呢玷禽?為了進(jìn)一步細(xì)化消息,有了Tag的概念呀打∈噶蓿可以通過Tag對(duì)相同消息進(jìn)行歸類,這樣用戶就可以只訂閱一部分的消息了(只訂閱部分Tag)
比如:有一個(gè)Topic叫做‘發(fā)貨’贬丛,下游消費(fèi)者希望可以根據(jù)貨源進(jìn)行不同的處理撩银,可以通過‘tag=北京’以及‘tag=上海’來區(qū)分不同的發(fā)貨源豺憔。下游消費(fèi)者额获,可以單獨(dú)訂閱‘上海’的貨物恭应,或者‘tag=上海|江蘇|浙江’來訂閱這三個(gè)地區(qū)的貨物抄邀,還可以‘tag=*’來訂閱全國(guó)的貨物。
Key
發(fā)送了某個(gè)消息昼榛,但是希望在后臺(tái)很方便的搜索到境肾,就要通過key了〉ㄓ欤可以根據(jù)key搜索到所有相關(guān)的Message奥喻。可以認(rèn)為RocketMQ內(nèi)部維護(hù)了一個(gè)非常大的HashMap莺掠,key就是這個(gè)key衫嵌,value就是Message,如果出現(xiàn)Hash沖突就用鏈表來報(bào)錯(cuò)對(duì)應(yīng)關(guān)系彻秆。
提問:
每次申請(qǐng)Topic好煩啊楔绞,索性申請(qǐng)個(gè)叫tp_all的topic算了结闸,然后內(nèi)部用tag來區(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ì)遇見這個(gè)問題鳖眼,某個(gè)消息誰發(fā)的黑毅?RocketMQ把發(fā)送者的身份抽象成了Producer Group,就是[發(fā)送組]钦讳。
簡(jiǎn)單點(diǎn):這個(gè)東西命名成項(xiàng)目名就行矿瘦,相同Producer Group保持相同業(yè)務(wù)行為
提問:
我的項(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這樣有問題么?
一個(gè)Topic有Producer Group:‘test_group’ 兩個(gè)項(xiàng)目都用了柜候,但是A項(xiàng)目發(fā)送的tag叫A衬衬,B項(xiàng)目發(fā)送的消息Tag是B,請(qǐng)問有問題么改橘??
Consumer
消費(fèi)者:把queue里面的消息拿出來用
消費(fèi)行為:如何處理通過Topic+Tag定位的消息
Consumer Group
重點(diǎn)玉控!重點(diǎn)飞主!重點(diǎn)!來了高诺,直接翻譯是‘消費(fèi)組’
一個(gè)RocketMQ集群是如何區(qū)分消費(fèi)者是誰的呢碌识?就是通過消費(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)目都重啟無數(shù)次了,RocketMQ是如何記錄消息消費(fèi)到什么地方了呢旅薄?
? ? 也是通過消費(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)位置而定)
提問:
兩個(gè)服務(wù),服務(wù)A和服務(wù)B凯沪,消費(fèi)相同集群的相同Topic第焰,既然服務(wù)不一樣,那么就算是定義了相同的consumer group也無所謂吧著洼?
常見問題:消費(fèi)組名字命名的不合理樟遣,上線后悄悄改回來行不行?
不小心用了別人的消費(fèi)組名身笤,悄悄改回來重新上線也沒什么問題吧豹悬?
常見問題:一個(gè)服務(wù)有消費(fèi)組A消費(fèi)3個(gè)Topic,有一次上線液荸,希望消費(fèi)4個(gè)Topic瞻佛。對(duì)于新消費(fèi)的消息希望可以灰度驗(yàn)證一段時(shí)間。請(qǐng)問有問題么娇钱?
消息延遲/積壓
消息隊(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)的是磁盤數(shù)據(jù)稽物,直接操作磁盤奄毡。磁盤肯定比內(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開源版本沒有多租戶隔離农猬,所以公共集群使用的過程中會(huì)有相互影響發(fā)生,鑒于此大家在上線前還是要合理評(píng)估自己的系統(tǒng)能力售淡。
提問:
消費(fèi)延遲太多了斤葱,業(yè)務(wù)上接受丟棄一部分消息,如何操作呢揖闸?
消息的處理線程太少了揍堕,想加大處理線程怎么辦?
自己搞個(gè)線程池處理消息是不是很贊汤纸?
InstanceName
這個(gè)概念比較尷尬衩茸。上面說的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è)值囊蓝。
提問:
要向兩個(gè)RocketMQ集群生產(chǎn)數(shù)據(jù),只需要設(shè)置不同的Producer Group即可令蛉?
要從兩個(gè)RocketMQ集群消費(fèi)數(shù)據(jù)聚霜,只需要設(shè)置不同的Consumer Group即可?