前不久踩了個坑,而這個坑跟 RocketMQ 推薦的一個最佳實(shí)踐有關(guān)。
看下我從官網(wǎng)的截圖,官方推薦一個應(yīng)用盡可能只用一個 topic,然后用 tags 來標(biāo)識子類型。
從訂單角度來看,可以用一個 Topic-Order,然后再用不同的 tag 來區(qū)分這是 3C 類的訂單,還是母嬰類的訂單等,然后下游應(yīng)用根據(jù)不同的需求過濾不同的 tag。
這樣的實(shí)現(xiàn)方式從業(yè)務(wù)上來看關(guān)系更清晰(有點(diǎn)樹狀的感覺),但是在實(shí)踐上有點(diǎn)問題。
問題和起因
一般而言,生產(chǎn)上同一個服務(wù)至少會部署兩臺機(jī)器,不僅僅是為了負(fù)載均衡,也是為了系統(tǒng)的可靠性,當(dāng)一臺機(jī)器意外掛了,另一臺可以扛起大旗。
我們在發(fā)服務(wù)的時候,都是分批發(fā)布。
這是為了驗(yàn)證新功能的正確性,不讓其一次性影響所有實(shí)例,我們會先發(fā)布一批,然后觀察下日志,確保無誤后繼續(xù)發(fā)布后續(xù)幾臺機(jī)器。
而這個操作再結(jié)合 RocketMQ 一個 Topic 多 tag 就會出現(xiàn)訂閱消息不一致的情況,導(dǎo)致丟消息。
原理分析
我們借用官網(wǎng)的圖來分析一下。
一般我們都用集群模式,以下描述默認(rèn)使用集群模式
從使用層來看,發(fā)送和消費(fèi)消息給我們最直觀的感受如下:
生產(chǎn)者往一個 Topic 發(fā)送消息,消費(fèi)者訂閱了這個 Topic 就能消費(fèi)到這個消息。
而實(shí)際上在 RocketMQ 中有隊(duì)列的概念:
也就是生產(chǎn)者往一個 Topic 發(fā)送消息時,消息會被分到不同的隊(duì)列中。
而屬于同一個消費(fèi)組的消費(fèi)者們會平分消費(fèi)這些隊(duì)列,從上圖可以看到 Topic A 分了三個隊(duì)列,分別是 MessageQueue 0、1、2。
而消費(fèi)組 ConsumerGroupA 中的 Consumer1 僅消費(fèi) MessageQueue0 和 MessageQueue1 這兩個隊(duì)列中的消息,而 Consumer2 僅消費(fèi) MessageQueue2。
這樣劃分后,Consumer1 是無法消費(fèi)到 MessageQueue2 中的消息的。
看到可能有人會說,這跟 tag 有什么關(guān)系嗎?沒錯,問題就在這個分割跟 tag 沒關(guān)系!
在默認(rèn)情況下生產(chǎn)者發(fā)送消息是以輪詢隊(duì)列的方式發(fā)送的。
比如現(xiàn)在 Producer A 要發(fā)送 TopicA-tag1、TopicA-tag2、TopicA-tag3 這三條數(shù)據(jù),輪詢發(fā)送后,MessageQueue 0、1、2 分別存儲了這 3 條消息。
假設(shè)同樣訂閱了 TopicA,但是 Consumer 1訂閱的 tag 是 tag1和 tag3,而 Consumer 2 訂閱的是 tag1、tag2,那么問題就來了。
按輪詢的順序 Consumer 1 要消費(fèi)的 tag3 被投遞到 MessageQueue2 這個隊(duì)列中,而 Consumer 1 又無法消費(fèi) MessageQueue2 中的消息,Consumer 2 能消費(fèi) MessageQueue2 中的消息,但偏偏它又不要 tag3 的消息。這樣一來 tag3 的這條消息就丟了,問題就出現(xiàn)了。
所以,在實(shí)踐中,我們要求同一個消費(fèi)組的消費(fèi)者的訂閱關(guān)系要保持一致。
也就是 Conusmer1 和 Conusmer2 需要訂閱一樣的 Topic、一樣的 tag,這樣消息才不會丟失。
再回到問題
現(xiàn)在我們已經(jīng)知道訂閱關(guān)系一致的重要性,但是有時候不得已就會“明知故犯”。
假設(shè)我們訂單服務(wù)線上一共部署了 5 臺,這 5 臺機(jī)器屬于同一個消費(fèi)組,因此它們負(fù)載均衡消費(fèi)有關(guān)訂單的消息,如 Topic-Order。
這 5 臺機(jī)器部署的都是同一套代碼,它們都訂閱了 Topic-Order,且 tag 是 A、B、C 三個。
這次發(fā)版需要訂單服務(wù)新增消費(fèi) Topic-Order 下的 tag D 消息,由于分批部署,所以先部署了 1 臺機(jī)器觀察。
而此時線上就出現(xiàn)了訂閱關(guān)系不一致的情況!5臺機(jī)器,有 1 臺訂閱了 Topic-Order tag A、B、C、D,而其他 4 臺訂閱了 Topic-Order tag A、B、C。
這段時間內(nèi)就出現(xiàn)了上述所說的丟消息的情況,如果有 Topic-Order tagD 的消息產(chǎn)生,那么就有可能會丟了。
明知有錯,不想犯,卻犯了!
針對這個場景,我暫時沒啥思路,不知道業(yè)界是否有什么方式可以優(yōu)雅的處理這個問題?歡迎各位留言指導(dǎo)或探討!
然后留個坑,如果一臺機(jī)器訂閱的是 tagA||tagB,而另一臺訂閱的是 tagB||tagA,這樣算訂閱消息一致嗎?
審核編輯:劉清
-
機(jī)器人
+關(guān)注
關(guān)注
211文章
28455瀏覽量
207265 -
過濾器
+關(guān)注
關(guān)注
1文章
430瀏覽量
19621
原文標(biāo)題:RocketMQ 最佳實(shí)踐之坑
文章出處:【微信號:芋道源碼,微信公眾號:芋道源碼】歡迎添加關(guān)注!文章轉(zhuǎn)載請注明出處。
發(fā)布評論請先 登錄
相關(guān)推薦
評論