如何保證訊息的順序性?

2021-10-10 10:41:07 字數 1655 閱讀 7468

如何保證訊息的順序性?

其實這個也是用 mq 的時候必問的話題,第一看看你了不了解順序這個事兒?第二看看你有沒有辦法保證訊息是有順序的?這是生產系統中常見的問題。

我舉個例子,我們以前做過乙個 mysql binlog 同步的系統,壓力還是非常大的,日同步資料要達到上億,就是說資料從乙個 mysql 庫原封不動地同步到另乙個 mysql 庫裡面去(mysql -> mysql)。常見的一點在於說比如大資料 team,就需要同步乙個 mysql 庫過來,對公司的業務系統的資料做各種複雜的操作。

你在 mysql 裡增刪改一條資料,對應出來了增刪改 3 條 binlog 日誌,接著這三條 binlog 傳送到 mq 裡面,再消費出來依次執行,起碼得保證人家是按照順序來的吧?不然本來是:增加、修改、刪除;你愣是換了順序給執行成刪除、修改、增加,不全錯了麼。

本來這個資料同步過來,應該最後這個資料被刪除了;結果你搞錯了這個順序,最後這個資料保留下來了,資料同步就出錯了。

先看看順序會錯亂的倆場景:

rabbitmq:乙個 queue,多個 consumer。比如,生產者向 rabbitmq 裡傳送了三條資料,順序依次是 data1/data2/data3,壓入的是 rabbitmq 的乙個記憶體佇列。有三個消費者分別從 mq 中消費這三條資料中的一條,結果消費者 2 先執行完操作,把 data2 存入資料庫,然後是 data1/data3。這不明顯亂了。

kafka:比如說我們建了乙個 topic,有三個 partition。生產者在寫的時候,其實可以指定乙個 key,比如說我們指定了某個訂單 id 作為 key,那麼這個訂單相關的資料,一定會被分發到同乙個 partition 中去,而且這個 partition 中的資料一定是有順序的。

消費者從 partition 中取出來資料的時候,也一定是有順序的。到這裡,順序還是 ok 的,沒有錯亂。接著,我們在消費者裡可能會搞多個執行緒來併發處理訊息。因為如果消費者是單執行緒消費處理,而處理比較耗時的話,比如處理一條訊息耗時幾十 ms,那麼 1 秒鐘只能處理幾十條訊息,這吞吐量太低了。而多個執行緒併發跑的話,順序可能就亂掉了。

rabbitmq

拆分多個 queue,每個 queue 乙個 consumer,就是多一些 queue 而已,確實是麻煩點;或者就乙個 queue 但是對應乙個 consumer,然後這個 consumer 內部用記憶體佇列做排隊,然後分發給底層不同的 worker 來處理。

kafka

乙個 topic,乙個 partition,乙個 consumer,內部單執行緒消費,單執行緒吞吐量太低,一般不會用這個。

寫 n 個記憶體 queue,具有相同 key 的資料都到同乙個記憶體 queue;然後對於 n 個執行緒,每個執行緒分別消費乙個記憶體 queue 即可,這樣就能保證順序性。

如何保證訊息的順序性?

我舉個例子,我們以前做過乙個 mysql binlog 同步的系統,壓力還是非常大的,日同步資料要達到上億,就是說資料從乙個 mysql 庫原封不動地同步到另乙個 mysql 庫裡面去 mysql mysql 常見的一點在於說比如大資料 team,就需要同步乙個 mysql 庫過來,對公司的業務系統...

如何保證訊息的順序性?

面試題 如何保證訊息的順序性?面試官心理分析 其實這個也是用 mq 的時候必問的話題,第一看看你了不了解順序這個事兒?第二看看你有沒有辦法保證訊息是有順序的?這是生產系統中常見的問題。面試題剖析 我舉個例子,我們以前做過乙個 mysql binlog 同步的系統,壓力還是非常大的,日同步資料要達到上...

如何保證訊息佇列訊息的順序性

舉個例子 有乙個mysql binlog 同步系統,壓力是非常大的,日同步資料達到了上億級別,就是將資料從乙個 mysql 庫當中原封不動的同步到另乙個 mysql 庫當中去 比較常見的就是大資料組需要幹的事情 假設在 mysql 當中增刪改了一條資料,對應的生產了三條 增刪改的 binlog 日誌...