kafka分布式的情況下,如何保證訊息的順序

時間 2021-05-12 01:11:53

1樓:瀟湘夜雨

由於問題比較寬泛,需要針對不同場景來分析,以下所有的分析都是基於同乙個partition下的場景細化,多partition下無法保障訊息的順序性,但是碰到如下場景還是需要調整引數。

場景一:設定了retries>0,並且max.in.flight.requests.per.connection>1

先說明下這兩個引數的含義:

retries

生產者從伺服器收到的錯誤有可能是臨時性的錯誤(比如分割槽找不到首領)。在這種情況下,retries 引數的值決定了生產者可以重發訊息的次數,如果達到這個次數,生產者會放棄重試並返回錯誤。

預設情況下,生產者會在每次重試之間等待 100ms,不過可以通過 retry.backoff.ms 引數來改變這個時間間隔。

建議在設定重試次數和重試時間間隔之前,先測試一下恢復乙個崩潰節點需要多少時間(比如所有分割槽選舉出首領需要多長時間),讓總的重試時間比 Kafka 集群從崩潰中恢復的時間長,否則生產者會過早地放棄重試。不過有些錯誤不是臨時性錯誤,沒辦法通過重試來解決(比如「訊息太大」錯誤)。

該引數指定了生產者在收到伺服器響應之前可以傳送多少個訊息。它的值越高,就會占用越多的記憶體,不過也會提公升吞吐量。把它設為 1 可以保證訊息是按照傳送的順序寫入伺服器的,即使發生了重試。

這種場景下無法保障單一partition的有序,一般來說要保障訊息的有序性,對於訊息的可靠性也是有要求的,所以一般retries可以設定為大於0,但是max.in.flight.

requests.per.connection設定為1即可,不過這樣就有乙個問題,導致了訊息的吞吐量大大降低。

再發散一下,max.in.flight.requests.per.connection保障訊息有序的邏輯原始碼時如何實現的呢?

在生產者訊息傳送執行緒Sender裡面sendProducerData方法,裡面有關於保障訊息有序的一段邏輯如下:

//如果需要保證訊息的強順序性,則快取對應 topic 分割槽物件,防止同一時間往同乙個 topic 分割槽傳送多條處於未完成狀態的訊息if(

guaranteeMessageOrder)}

實際上就是將本批次訊息所在的分割槽資訊新增到乙個集合中,以保障每個topic下的該分割槽只有乙個批次傳送,如下:

public

void

mutePartition

(TopicPartitiontp)

場景二:需要提公升吞吐量max.in.flight.requests.per.connection設定大於1

此場景下業務要保障訊息的吞吐量,那麼max.in.flight.

requests.per.connection必然就會選擇更大的乙個閾值,但是此場景還能保障訊息有序性嗎?

答案是肯定的,可以設定enable.idempotence=true,開啟生產者的冪等生產,可以解決順序性問題,並且允許max.in.

flight.requests.per.

connection設定大於1

2樓:行空

如果Kafka要保證多個partition有序,不僅broker儲存的資料要保持順序,消費時也要按序消費。假設partition1堵了,為了有序,那partition2以及後續的分割槽也不能被消費,這種情況下,Kafka 就退化成了單一佇列,毫無併發性可言,極大降低系統效能。因此Kafka使用多partition的概念,並且只保證單partition有序。

這樣不同partiiton之間不會干擾對方。

producer發訊息到佇列時,通過加鎖保證有序

現在假設兩個問題

broker leader在給producer傳送ack時,因網路原因超時,那麼Producer 將重試,造成訊息重複。

先後兩條訊息傳送。t1時刻msg1傳送失敗,msg2傳送成功,t2時刻msg1重試後傳送成功。造成亂序。

2.解決重試機制引起的訊息亂序

為實現Producer的冪等性,Kafka引入了Producer ID(即PID)和Sequence Number。對於每個PID,該Producer傳送訊息的每個都對應乙個單調遞增的Sequence Number。同樣,Broker端也會為每個維護乙個序號,並且每Commit一條訊息時將其對應序號遞增。

對於接收的每條訊息,如果其序號比Broker維護的序號)大一,則Broker會接受它,否則將其丟棄:

如果訊息序號比Broker維護的序號差值比一大,說明中間有資料尚未寫入,即亂序,此時Broker拒絕該訊息,Producer丟擲InvalidSequenceNumber

如果訊息序號小於等於Broker維護的序號,說明該訊息已被儲存,即為重複訊息,Broker直接丟棄該訊息,Producer丟擲DuplicateSequenceNumber

Sender傳送失敗後會重試,這樣可以保證每個訊息都被傳送到broker

3樓:大資料技術架構

一般業務不要求全域性有序,kafka只能保證同乙個partition內訊息有序,不能保證不同partition之間有序,因此業務只能充分利用單個partition內有序這個特點。

舉乙個資料同步的例子,假設訂單表,每個訂單是有狀態的,我們要保證同乙個訂單的多次修改記錄達到kafka裡的順序不能亂,我們可以根據訂單主鍵判斷該落哪乙個分割槽,用的比較多的策略大概是 abs(hash(主鍵)) % partition_num,如此就能保證同一筆訂單落到同乙個partition 繼爾保證了順序。 一般情況下這樣資料也是均衡的。

4樓:

我們都知道不同的Partition是不保證有序的, 因為都不在一台機器上, 也沒有乙個中心化的協調的地方, 誰先誰後肯定是沒法保證的.

那單個Partition怎麼就能實現有序啦? 採用WAL的方式就一定是有序的?

首先我們要搞清楚這個有序說的是什麼:

這個有序是說按照到達伺服器的message有序嗎?

這種最弱的有序, 隨便弄個全域性鎖也是可以保證的.

想讓客戶端生產出來的訊息有序的寫入日誌?

奧秘就在乙個producer裡面有乙個queue, 用來對你要寫的log進行排序然後batch的形式傳送.

這個時候就需要

this.guaranteeMessageOrder = (config.getInt(ProducerConfig.

MAX_IN_FLIGHT_REQUESTS_PER_CONNECTION) == 1)

如果只有乙個connection, m每次send的時候都會mute對應TP, 阻止併發.這樣才可以保證有序.

多個客戶端同時對同乙個topic partition寫還能保證有序嗎?

不能, 原因和多個partion無序是一樣的

5樓:

Kafka 中傳送1條訊息的時候,可以指定(topic, partition, key) 3個引數。partiton 和 key 是可選的。如果你指定了 partition,那就是所有訊息發往同1個 partition,就是有序的。

並且在消費端,Kafka 保證,1個 partition 只能被1個 consumer 消費。或者你指定 key(比如 order id),具有同1個 key 的所有訊息,會發往同1個 partition。也是有序的。

6樓:cococonut

在Producer往Kafka插入資料時,控制同一Key分發到同一Partition,並且設定引數max.in.flight.

requests.per.connection=1,也即同乙個鏈結只能傳送一條訊息,如此便可嚴格保證Kafka訊息的順序

7樓:有雨

其他回答很多了,其實這個問題稍微查查資料就知道。同分割槽是順序的,如果乙個topic只有乙個分割槽,那麼就是絕對有序的,一般都有多個分割槽,所以只是大致有序。

8樓:靜默

Apache Kafka官方保證了partition內部的資料有效性(追加寫、offset讀);為了提高Topic的併發吞吐能力,可以提高Topic的partition數,並通過設定partition的replica來保證資料高可靠;

但是在多個Partition時,不能保證Topic級別的資料有序性。

因此,如果你們就像死磕kafka,但是對資料有序性有嚴格要求,那我建議:

建立Topic只指定1個partition,這樣的壞處就是磨滅了kafka最優秀的特性。

所以可以思考下是不是技術選型有問題, kafka本身適合與流式大資料量,要求高吞吐,對資料有序性要求不嚴格的場景。

9樓:至尊寶

落到乙個例項是有序的,方法就是大家說的,落到不同例項是沒辦法保證有序的,如果非要保證,在訊息裡加乙個單調遞增的字段,那麼這樣需要乙個能產生遞增欄位的服務,成本很大,最好說一下具體場景,我想肯定能通過別的設計解決。

曾經遇到的乙個場景,消費 q(q裡的訊息是更新,建立等事件),拿到了q去反查服務獲取資料,推送給第三方,第三方資料落庫,當連續產生對同一條資料的更新情況,第三方收到的資料順序有可能錯了,這時候第三方落庫就會出現資料與我方不一致的情況,解決辦法加個時間戳,第三方判斷時間。

在資料更新特別頻繁的情況下,時間戳不起作用了,那就使用樂觀鎖,判斷version。

10樓:

Kafka分布式的單位是partition,同乙個partition用乙個write ahead log組織,所以可以保證FIFO的順序。不同partition之間不能保證順序。

11樓:胡慢慢滾雪球

kafka只能保證partition內是有序的,但是partition間的有序是沒辦法的。

打造高效能高可用的搜尋服務——愛奇藝搜尋架構實踐

可以看下愛奇藝的搜尋架構,直接拖到18:30,他們是從業務上把需要有序的打到同乙個partition,也是一種思路,而且廣泛使用。因為大多數情況只需要業務上保證有序就可以,不用全域性有序。

分布式的環境下, MySQL和Redis如何保持資料的一致性?

EnjoyMoving 資料庫和快取之間一般不需要強一致性。一般快取是這樣的 讀的順序是先讀快取,後讀資料庫 寫的順序是先寫資料庫,然後寫快取 每次更新了相關的資料,都要把該快取清理掉 為了避免極端條件下造成的快取與資料庫之間的資料不一致,快取需要設定乙個失效時間。時間到了,快取自動被清理,達到快取...

通常情況下,各種型別和規模發分布式電站可以供給多少人口的用電?

已登出 如前兩位知友所言,變數太多,無法衡量。我在這裡補充一點我的見解。要考慮這個微網是不是和大網並在一起。如果不是,那麼僅僅依靠光伏或者風電是不行的,在沒有配置大容量高功率儲能的前提下,風電和光伏的不穩定性對於微網而言,簡直就是毒藥。居民用電也就凑活了,看著電視被突然停電反正忍一下就算了,工廠怎麼...

如何理解 Git 的分布式?

body no Git看這裡你所有的疑問都在文件裡 所以以後來知乎提問前 先去看看文件 我已經看了5遍了 大多數知乎的技術性問題 都可以在文件中找到解決方案 主觀性的除外 因此先去看文件吧 我覺得要深入理解Git,還是得看原始碼。相較於其他的 如 svn,甚至 hg 我覺得 git 的實現更像乙個 ...