一、Kafka的特性
kafka中,寫入一個partition分區中的數據是一定有順序的。
kafka中一個消費者消費一個partition的數據,消費者取出數據時,也是有順序的。
訪問Kafka技術專欄,瞭解更多的技術細節和項目代碼。
專欄
Kafka v2.3 快速入門與實踐
33.9幣
54人已購
二、多線程消費會導致消息亂序
比如說我們建了一個 topic,有三個 partition。生產者在寫的時候,其實可以指定一個 key,比如說我們指定了某個訂單 id 作為 key,那麼這個訂單相關的數據,一定會被分發到同一個 partition 中去,而且這個 partition 中的數據一定是有順序的。
消費者從 partition 中取出來數據的時候,也一定是有順序的。到這裡,順序還是 ok 的,沒有錯亂。
接著,我們在消費者裡可能會搞多個線程來併發處理消息。因為如果消費者是單線程消費處理,而處理比較耗時的話,比如處理一條消息耗時幾十 ms,那麼 1 秒鐘只能處理幾十條消息,這吞吐量太低了。而多個線程併發跑的話,順序可能就亂掉了。
專欄
Spring Cloud微服務架構項目實戰
33.9幣
44人已購
由於消費者消費消息之後,有可能交給很多個線程去處理數據(如下圖),這樣就導致數據順序錯亂。
需要關注如下幾個知識點:
- 寫入一個partition中的數據,一定是有順序的;
- 生產者在寫消息的時候,可以指定一個key,比如指定訂單的id作為key;則同一個訂單相關數據,一定會分發到一個partition中去;
- 消費者從partition中取出數據的時候,一定是有順序的;
專欄
SkyWalking分佈式鏈路追蹤和監控
19.8幣
53人已購
三、解決消息的有序性
方案1:
一個 topic,一個 partition,一個 consumer,內部單線程消費,單線程吞吐量太低,一般不會用這個。或者針對前面的方式進行改良,一個topic,多個partition,多個consumer 實例。
這種方式實現起來比較簡單快捷,如下圖所示,每一個消費者實例負責處理一個partition中的消息。
一個分區Partition不能被同一個消費組(Consumer Group)中多個消費者Consumer消息,這樣就保證了Partition中消息消費的有序性。
方案2:
為了保證一個消費者中多個線程去處理時,不會使得消息的順序被打亂,則可以在消費者中,消息分發至不同的線程時,加一個隊列,消費者去做hash分發,將需要放在一起的數據,分發至同一個隊列中,最後多個線程從隊列中取數據,如下圖所示。
寫 N 個內存 queue,具有相同 key 的數據都分發到同一個內存 queue;然後對於 N 個線程,每個線程分別消費一個內存 queue 即可,這樣就能保證順序性。
獲取更多Elasticsearch設計細節和演示項目源代碼,可訪問Elasticsearch 7.x 訂單中心技術專欄。
專欄
Elasticsearch 7.x訂單中心實戰
33.9幣
109人已購