一窥浪、基本概念
1 消息(Message)
消息是指,消息系統(tǒng)所傳輸信息的物理載體,生產(chǎn)和消費數(shù)據(jù)的最小單位瘟滨,每條消息必須屬于一個主
題。
2 主題(Topic)
Topic表示一類消息的集合绰垂,每個主題包含若干條消息室奏,每條消息只能屬于一個主題,是RocketMQ進(jìn)行
消息訂閱的基本單位劲装。 topic:message 1:n message:topic 1:1
一個生產(chǎn)者可以同時發(fā)送多種Topic的消息胧沫;而一個消費者只對某種特定的Topic感興趣,即只可以訂閱
和消費一種Topic的消息占业。 producer:topic 1:n consumer:topic 1:1
3 標(biāo)簽(Tag)
為消息設(shè)置的標(biāo)簽绒怨,用于同一主題下區(qū)分不同類型的消息。來自同一業(yè)務(wù)單元的消息谦疾,可以根據(jù)不同業(yè)
務(wù)目的在同一主題下設(shè)置不同標(biāo)簽南蹂。標(biāo)簽?zāi)軌蛴行У乇3执a的清晰度和連貫性,并優(yōu)化RocketMQ提
供的查詢系統(tǒng)念恍。消費者可以根據(jù)Tag實現(xiàn)對不同子主題的不同消費邏輯六剥,實現(xiàn)更好的擴(kuò)展性。
Topic是消息的一級分類峰伙,Tag是消息的二級分類疗疟。
Topic:貨物
tag=上海
tag=江蘇
tag=浙江
------- 消費者 -----
topic=貨物 tag = 上海
topic=貨物 tag = 上海|浙江
topic=貨物 tag = *
4 隊列(Queue)
存儲消息的物理實體。一個Topic中可以包含多個Queue瞳氓,每個Queue中存放的就是該Topic的消息策彤。一
個Topic的Queue也被稱為一個Topic中消息的分區(qū)(Partition)。
一個Topic的Queue中的消息只能被一個消費者組中的一個消費者消費。一個Queue中的消息不允許同
一個消費者組中的多個消費者同時消費店诗。
5 消息標(biāo)識(MessageId/Key)
RocketMQ中每個消息擁有唯一的MessageId裹刮,且可以攜帶具有業(yè)務(wù)標(biāo)識的Key,以方便對消息的查詢庞瘸。
不過需要注意的是捧弃,MessageId有兩個:在生產(chǎn)者send()消息時會自動生成一個MessageId(msgId),
當(dāng)消息到達(dá)Broker后恕洲,Broker也會自動生成一個MessageId(offsetMsgId)塔橡。msgId、offsetMsgId與key都
稱為消息標(biāo)識霜第。
msgId:由producer端生成葛家,其生成規(guī)則為:
producerIp + 進(jìn)程pid + MessageClientIDSetter類的ClassLoader的hashCode +
當(dāng)前時間 + AutomicInteger自增計數(shù)器
offsetMsgId:由broker端生成,其生成規(guī)則為:brokerIp + 物理分區(qū)的offset(Queue中的
偏移量)
key:由用戶指定的業(yè)務(wù)相關(guān)的唯一標(biāo)識
二泌类、系統(tǒng)架構(gòu)
1 Producer
消息生產(chǎn)者癞谒,負(fù)責(zé)生產(chǎn)消息。Producer通過MQ的負(fù)載均衡模塊選擇相應(yīng)的Broker集群隊列進(jìn)行消息投遞刃榨,投遞的過程支持快速失敗并且低延遲弹砚。
例如,業(yè)務(wù)系統(tǒng)產(chǎn)生的日志寫入到MQ的過程枢希,就是消息生產(chǎn)的過程
再如桌吃,電商平臺中用戶提交的秒殺請求寫入到MQ的過程,就是消息生產(chǎn)的過程
RocketMQ中的消息生產(chǎn)者都是以生產(chǎn)者組(Producer Group)的形式出現(xiàn)的苞轿。生產(chǎn)者組是同一類生產(chǎn)者的集合茅诱,這類Producer發(fā)送相同Topic類型的消息。一個生產(chǎn)者組可以同時發(fā)送多個主題的消息搬卒。
2 Consumer
消息消費者瑟俭,負(fù)責(zé)消費消息。一個消息消費者會從Broker服務(wù)器中獲取到消息契邀,并對消息進(jìn)行相關(guān)業(yè)務(wù)
處理摆寄。
例如,QoS系統(tǒng)從MQ中讀取日志坯门,并對日志進(jìn)行解析處理的過程就是消息消費的過程微饥。
再如,電商平臺的業(yè)務(wù)系統(tǒng)從MQ中讀取到秒殺請求古戴,并對請求進(jìn)行處理的過程就是消息消費的
過程欠橘。
RocketMQ中的消息消費者都是以消費者組(Consumer Group)的形式出現(xiàn)的。消費者組是同一類消費者的集合允瞧,這類Consumer消費的是同一個Topic類型的消息简软。消費者組使得在消息消費方面,實現(xiàn)負(fù)載均衡(將一個Topic中的不同的Queue平均分配給同一個Consumer Group的不同的Consumer述暂,注意痹升,并不是將消息負(fù)載均衡)和容錯(一個Consmer掛了,該Consumer Group中的其它Consumer可以接著消費原Consumer消費的Queue)的目標(biāo)變得非常容易畦韭。
Name Server
功能介紹
NameServer是一個Broker與Topic路由的注冊中心疼蛾,支持Broker的動態(tài)注冊與發(fā)現(xiàn)。
RocketMQ的思想來自于Kafka艺配,而Kafka是依賴了Zookeeper的察郁。所以,在RocketMQ的早期版本转唉,即在MetaQ v1.0與v2.0版本中皮钠,也是依賴于Zookeeper的。從MetaQ v3.0赠法,即RocketMQ開始去掉了Zookeeper依賴麦轰,使用了自己的NameServer。
主要包括兩個功能:
- Broker管理:接受Broker集群的注冊信息并且保存下來作為路由信息的基本數(shù)據(jù)砖织;提供心跳檢測機(jī)制款侵,檢查Broker是否還存活。
- 路由信息管理:每個NameServer中都保存著Broker集群的整個路由信息和用于客戶端查詢的隊列信息侧纯。Producer和Conumser通過NameServer可以獲取整個Broker集群的路由信息新锈,從而進(jìn)行消息的投遞和消費。
路由注冊
NameServer通常也是以集群的方式部署眶熬,不過妹笆,NameServer是無狀態(tài)的,即NameServer集群中的各個節(jié)點間是無差異的聋涨,各節(jié)點間相互不進(jìn)行信息通訊晾浴。那各節(jié)點中的數(shù)據(jù)是如何進(jìn)行數(shù)據(jù)同步的呢?在Broker節(jié)點啟動時牍白,輪詢NameServer列表脊凰,與每個NameServer節(jié)點建立長連接,發(fā)起注冊請求茂腥。在NameServer內(nèi)部維護(hù)著?個Broker列表狸涌,用來動態(tài)存儲Broker的信息。注意最岗,這是與其它像zk帕胆、Eureka、Nacos等注冊中心不同的地方般渡。這種NameServer的無狀態(tài)方式懒豹,有什么優(yōu)缺點:
- 優(yōu)點:NameServer集群搭建簡單芙盘,擴(kuò)容簡單。
- 缺點:對于Broker脸秽,必須明確指出所有NameServer地址儒老。否則未指出的將不會去注冊。也正因為如此记餐,NameServer并不能隨便擴(kuò)容驮樊。因為,若Broker不重新配置片酝,新增的NameServer對于Broker來說是不可見的囚衔,其不會向這個NameServer進(jìn)行注冊。
Broker節(jié)點為了證明自己是活著的雕沿,為了維護(hù)與NameServer間的長連接练湿,會將最新的信息以心跳包的
方式上報給NameServer,每30秒發(fā)送一次心跳审轮。心跳包中包含 BrokerId鞠鲜、Broker地址(IP+Port)、
Broker名稱断国、Broker所屬集群名稱等等贤姆。NameServer在接收到心跳包后,會更新心跳時間戳稳衬,記錄這
個Broker的最新存活時間
路由剔除
由于Broker關(guān)機(jī)霞捡、宕機(jī)或網(wǎng)絡(luò)抖動等原因,NameServer沒有收到Broker的心跳薄疚,NameServer可能會將其從Broker列表中剔除碧信。
NameServer中有?個定時任務(wù),每隔10秒就會掃描?次Broker表街夭,查看每一個Broker的最新心跳時間戳距離當(dāng)前時間是否超過120秒砰碴,如果超過,則會判定Broker失效板丽,然后將其從Broker列表中剔除呈枉。
- 擴(kuò)展:對于RocketMQ日常運維工作,例如Broker升級埃碱,需要停掉Broker的工作猖辫。OP需要怎么做?
OP需要將Broker的讀寫權(quán)限禁掉砚殿。一旦client(Consumer或Producer)向broker發(fā)送請求啃憎,都會收到broker的NO_PERMISSION響應(yīng),然后client會進(jìn)行對其它Broker的重試似炎。當(dāng)OP觀察到這個Broker沒有流量后辛萍,再關(guān)閉它悯姊,實現(xiàn)Broker從NameServer的移除。
路由發(fā)現(xiàn)
RocketMQ的路由發(fā)現(xiàn)采用的是Pull模型贩毕。當(dāng)Topic路由信息出現(xiàn)變化時挠轴,NameServer不會主動推送給客戶端,而是客戶端定時拉取主題最新的路由耳幢。默認(rèn)客戶端每30秒會拉取一次最新的路由。
客戶端NameServer選擇策略
這里的客戶端指的是Producer與Consumer
客戶端在配置時必須要寫上NameServer集群的地址欧啤,那么客戶端到底連接的是哪個NameServer節(jié)點呢睛藻?客戶端首先會生產(chǎn)一個隨機(jī)數(shù),然后再與NameServer節(jié)點數(shù)量取模邢隧,此時得到的就是所要連接的節(jié)點索引店印,然后就會進(jìn)行連接。如果連接失敗倒慧,則會采用round-robin策略按摘,逐個嘗試著去連接其它節(jié)點。
首先采用的是隨機(jī)策略進(jìn)行的選擇纫谅,失敗后采用的是輪詢策略炫贤。
擴(kuò)展:Zookeeper Client是如何選擇Zookeeper Server的?
簡單來說就是付秕,經(jīng)過兩次Shuf? e兰珍,然后選擇第一臺Zookeeper Server。
詳細(xì)說就是询吴,將配置文件中的zk server地址進(jìn)行第一次shuf? e掠河,然后隨機(jī)選擇一個。這個選擇出的一般都是一個hostname猛计。然后獲取到該hostname對應(yīng)的所有ip唠摹,再對這些ip進(jìn)行第二次shuffle,從shuffle過的結(jié)果中取第一個server地址進(jìn)行連接奉瘤。
4 Broker
功能介紹
Broker充當(dāng)著消息中轉(zhuǎn)角色勾拉,負(fù)責(zé)存儲消息、轉(zhuǎn)發(fā)消息盗温。Broker在RocketMQ系統(tǒng)中負(fù)責(zé)接收并存儲從生產(chǎn)者發(fā)送來的消息望艺,同時為消費者的拉取請求作準(zhǔn)備。Broker同時也存儲著消息相關(guān)的元數(shù)據(jù)肌访,包括消費者組消費進(jìn)度偏移offset找默、主題、隊列等吼驶。
Kafka 0.8版本之后惩激,offset是存放在Broker中的店煞,之前版本是存放在Zookeeper中的。