分佈式場景下Kafka消息順序性的思考

在業務中使用kafka發送消息異步消費的場景,而且須要實如今消費時實現順序消費, 利用kafka在partition內消息有序的特色,實現消息消費時的有序性。網絡

一、在發送消息時,經過指定partition hash
二、consumer 消費消息時,須要使用親緣性線程池進行消費,才能實現消息的基本有序。不然即便經過發送時指定partition,在消費端因爲線程池的異步消費,消息之間的處理都是併發進行的,消息就會被打亂。

上面的方式基本能夠實現消息的消費順序性,除了在極端場景下,好比:併發

一、進程A 在T0時刻發送一個消息A
二、進程B在T1時刻發送了一個消息B。

  因爲T1>T0,而且進程A和進程B發送消息都是同一個hash partition,消息理論上在partition內消息A是在消息B前被消費的。但假如進程A和進程B出於不一樣的機房等緣由,致使在發送消息時進程A的消息因爲網絡緣由,要比進程B更晚發送成功,那麼就會致使消息B是在消息A以前。異步

多集羣模式下分佈式

因爲kafka的有序性,只是在單集羣的單partition內是有效的,因此當多集羣模式下,各個集羣之間的消息就不知足了有序的條件。雖然因爲每一個集羣都是使用相同的配置,都映射同一個consumer進程消費,以下:spa

 

可是因爲cluster-1-partition-5和cluster-2-partition-5兩個partition之間的是不一樣的partition,因此沒有辦法作到絕對有序。線程

 同時因爲conusmer-1會出現跨機房消費的多個集羣的狀況,因此本來在單集羣模式下,因爲網絡耗時而致使的消息前後順序,在多集羣狀況下就會增大。目前跨集羣消費延遲在2-10ms之間,因此在實際業務處理中遇到了消息A比消息B早發送,在消息B先到達的場景。
 blog

io瓶頸

因爲須要在consume端實現順序消費,須要使用親緣性線程池以確保同一個sku在同一個線程中消費消息。這種方式當某個sku的消息量特別大時,那麼就會阻塞了io線程,致使其餘消息也出現大量延遲。目前默認io線程拉取消息按broker來的,應該是等同於broker數量。雖然能夠增長io線程數來減緩這個狀況,但依然會存在這個場景。
 進程

總結

  在分佈式場景下要實現消息消費強順序性須要付出很大的成本,而且須要作到絕對順序十分困難。若是能夠容忍這個消費的無序性,那麼每每就不須要用到順序消費了。 以上分析爲實際應用中遇到的坑,僅供參考,歡迎拍磚。
ps:
  業務進程在發送kafka消息後,會有一個linger時間,等待linger時間以後再發送.rem

相關文章
相關標籤/搜索