消息中間件面試題:如何保證消息的順序性

面試題

如何保證消息的順序性?

消息中間件各種面試題:
消息中間件面試題:消息丟失怎么辦?
消息中間件面試題:消息隊(duì)列的優(yōu)缺點(diǎn),區(qū)別
消息中間件面試題:消息中間件的高可用
消息中間件面試題:如何保證消息的順序性
消息中間件面試題:如何保證消息不被重復(fù)消費(fèi)
消息中間件面試題:如何解決消息隊(duì)列的延時(shí)以及過(guò)期失效問(wèn)題?消息隊(duì)列滿了以后該怎么處理?有幾百萬(wàn)消息持續(xù)積壓幾小時(shí)呢?
消息中間件面試題:如果讓你寫一個(gè)消息隊(duì)列,該如何進(jìn)行架構(gòu)設(shè)計(jì)?

面試題剖析

我舉個(gè)例子,我們以前做過(guò)一個(gè) mysql binlog 同步的系統(tǒng),壓力還是非常大的,日同步數(shù)據(jù)要達(dá)到上億,就是說(shuō)數(shù)據(jù)從一個(gè) mysql 庫(kù)原封不動(dòng)地同步到另一個(gè) mysql 庫(kù)里面去(mysql -> mysql)。常見(jiàn)的一點(diǎn)在于說(shuō)比如大數(shù)據(jù) team,就需要同步一個(gè) mysql 庫(kù)過(guò)來(lái),對(duì)公司的業(yè)務(wù)系統(tǒng)的數(shù)據(jù)做各種復(fù)雜的操作。

你在 mysql 里增刪改一條數(shù)據(jù),對(duì)應(yīng)出來(lái)了增刪改 3 條 binlog 日志,接著這三條 binlog 發(fā)送到 MQ 里面,再消費(fèi)出來(lái)依次執(zhí)行,起碼得保證人家是按照順序來(lái)的吧?不然本來(lái)是:增加、修改、刪除;你楞是換了順序給執(zhí)行成刪除、修改、增加,不全錯(cuò)了么。

本來(lái)這個(gè)數(shù)據(jù)同步過(guò)來(lái),應(yīng)該最后這個(gè)數(shù)據(jù)被刪除了;結(jié)果你搞錯(cuò)了這個(gè)順序,最后這個(gè)數(shù)據(jù)保留下來(lái)了,數(shù)據(jù)同步就出錯(cuò)了。

先看看順序會(huì)錯(cuò)亂的倆場(chǎng)景:

  • RabbitMQ:一個(gè) queue,多個(gè) consumer。比如,生產(chǎn)者向 RabbitMQ 里發(fā)送了三條數(shù)據(jù),順序依次是 data1/data2/data3,壓入的是 RabbitMQ 的一個(gè)內(nèi)存隊(duì)列。有三個(gè)消費(fèi)者分別從 MQ 中消費(fèi)這三條數(shù)據(jù)中的一條,結(jié)果消費(fèi)者2先執(zhí)行完操作,把 data2 存入數(shù)據(jù)庫(kù),然后是 data1/data3。這不明顯亂了。
rabbitmq-order-01
  • Kafka:比如說(shuō)我們建了一個(gè) topic,有三個(gè) partition。生產(chǎn)者在寫的時(shí)候,其實(shí)可以指定一個(gè) key,比如說(shuō)我們指定了某個(gè)訂單 id 作為 key,那么這個(gè)訂單相關(guān)的數(shù)據(jù),一定會(huì)被分發(fā)到同一個(gè) partition 中去,而且這個(gè) partition 中的數(shù)據(jù)一定是有順序的。
    消費(fèi)者從 partition 中取出來(lái)數(shù)據(jù)的時(shí)候,也一定是有順序的。到這里,順序還是 ok 的,沒(méi)有錯(cuò)亂。接著,我們?cè)谙M(fèi)者里可能會(huì)搞多個(gè)線程來(lái)并發(fā)處理消息。因?yàn)槿绻M(fèi)者是單線程消費(fèi)處理,而處理比較耗時(shí)的話,比如處理一條消息耗時(shí)幾十 ms,那么 1 秒鐘只能處理幾十條消息,這吞吐量太低了。而多個(gè)線程并發(fā)跑的話,順序可能就亂掉了。
kafka-order-01

解決方案

RabbitMQ

拆分多個(gè) queue,每個(gè) queue 一個(gè) consumer,就是多一些 queue 而已,確實(shí)是麻煩點(diǎn);或者就一個(gè) queue 但是對(duì)應(yīng)一個(gè) consumer,然后這個(gè) consumer 內(nèi)部用內(nèi)存隊(duì)列做排隊(duì),然后分發(fā)給底層不同的 worker 來(lái)處理。


rabbitmq-order-02

Kafka

  • 一個(gè) topic,一個(gè) partition,一個(gè) consumer,內(nèi)部單線程消費(fèi),單線程吞吐量太低,一般不會(huì)用這個(gè)。
  • 寫 N 個(gè)內(nèi)存 queue,具有相同 key 的數(shù)據(jù)都到同一個(gè)內(nèi)存 queue;然后對(duì)于 N 個(gè)線程,每個(gè)線程分別消費(fèi)一個(gè)內(nèi)存 queue 即可,這樣就能保證順序性。
kafka-order-02

關(guān)注我,這里只有干貨!

本文原創(chuàng)地址:https://jsbintask.cn/2019/01/28/interview/interview-middleware-order/,轉(zhuǎn)載請(qǐng)注明出處。

最后編輯于
?著作權(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)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

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

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