如何克服 Apache Kafka中的資料順序問題 - DATAVERSITY
通過了解 Apache Kafka 如何對資料進行排序,您可以確保您的資料或應用程式保持良好的工作狀態。
儘管Apache Kafka已經贏得了作為功能強大的分散式流媒體平臺的聲譽,但在確保按您希望的順序儲存和檢索資料方面,它還具有一些複雜性。
為了捕獲流資料,Kafka 將記錄釋出到多個 Kafka消費者可以訂閱和檢索資料的主題、類別或提要名稱。Kafka 叢集為每個主題維護一個分割槽日誌,來自同一個生產者的所有訊息傳送到同一個分割槽,並按照它們到達的順序新增。通過這種方式,分割槽是結構化的提交日誌,儲存有序且不可變的記錄序列。新增到分割槽的每條記錄都分配了一個偏移量,一個唯一的順序 ID。
在 Kafka 中按照你喜歡的順序接收資料的挑戰有一個相對簡單的解決方案:分割槽保持嚴格的順序,並且總是按照資料新增到分割槽的順序將資料傳送給消費者。但是,Kafka 不會維護跨多個分割槽的主題的總記錄順序。
讓我們使用一個”鍵key“的例子,它允許你向生產者記錄新增鍵。我們將向一個有兩個分割槽的Kafka主題傳送四個包含鍵key的訊息。
有四個不同的鍵——Costco、Walmart、Target 和 Best Buy,並在叢集中雜湊並分佈到分割槽中,
現在我們將再傳送另外四條訊息,Kafka 將向已經使用現有Key的分割槽傳送訊息:
所有 Costco 或 Walmart 記錄都在分割槽 1 中,所有 Target 或 Best Buy 記錄都在分割槽 2 中。這些記錄按它們傳送到這些分割槽的順序排列。
接下來,讓我們看看如果向叢集新增更多分割槽會發生什麼,我們可能希望這樣做以便以更健康的方式平衡資料。
新增新的一個分割槽後,我們將觸發重新平衡事件:
資料保持良好的鍵結構,所有 Best Buy 資料都平衡到分割槽 3。如果我們向主題新增另外四條訊息,情況將保持不變:
資料進入儲存已建立key的分割槽。但是,因為一個分割槽儲存的資料是其他分割槽的兩倍,所以新增第四個分割槽並觸發另一個重新平衡是合乎邏輯的:
結果是資料集的健康平衡。
確保資料始終按順序傳送
其他問題
還有許多其他問題可能導致資料在 Kafka 中無序到達,包括代理或客戶端故障以及重新嘗試傳送資料產生的混亂。為了解決這些問題,讓我們首先仔細看看 Kafka 生產者。
以下是顯示 Kafka 生產者如何工作的高階概述:
至少,ProducerRecord 物件包括要將資料傳送到的主題和一個值。它還可以包括要使用的指定分割槽和Key。在上面的示例中,我建議您始終使用Key。如果不這樣做,資料將迴圈分配到任何沒有組織的分割槽。ProducerRecord 中的資料接下來使用 Serializer 進行編碼,然後 Partitioner 演算法決定資料的去向。
上圖左側概述的重試機制是一個經常發生資料順序問題的區域。例如,假設您嘗試向 Kafka 傳送兩條記錄,但一條由於網路問題而失敗,而另一條通過。當您嘗試重新傳送資料時,存在資料亂序的風險,因為您現在同時向 Kafka 傳送兩個請求。
您可以通過將 max.in.flight.requests.per.connection 設定為 1 來解決此問題。如果設定為多個(並且 retries 引數非零),則代理可能無法成功寫入第一批訊息同時寫第二個,因為它也被允許在飛行中,然後成功重試第一批,將他們的順序交換到你不想要的順序。相比之下,將 max.in.flight.requests.per.connection 設定為 1 可確保這些請求按順序依次發生。
在順序至關重要的場景中,我建議將 in.flight.requests.per.session 設定為 1;這可確保在重試訊息批處理時不會傳送其他訊息。然而,這種策略嚴重限制了生產者的吞吐量,只有在順序必不可少的情況下才應該使用。將允許的重試設定為零似乎是一種可能的選擇,但是,如果對系統可靠性的影響使其成為不可選項。
實現“恰好一次的訊息傳遞”
Kafka 包括三種不同的訊息傳遞方法,每種方法都有自己的保證行為:
- At-Once Message Delivery:此方法將傳遞一次訊息批處理,或從不傳遞。這消除了重新傳送相同訊息的風險,但也允許它們丟失。
- At-Least-Once Message Delivery:此方法在訊息傳遞之前不會停止。雖然傳遞總是成功並且沒有訊息丟失,但是它們可以被多次傳遞。
- Exactly-Once Message Delivery:這種方法保證所有訊息的傳遞,並且每個訊息只傳遞一次。雖然會發生失敗和重試,但 Exactly-Once Message Delivery 會採取額外的步驟來確保單次成功傳遞。
顯然,Exactly-Once Message Delivery 是保持資料順序的理想選擇。
將 Exactly-Once Message Delivery 付諸實踐需要利用三個元件:冪等生產者、跨分割槽事務和事務消費者。
- 1) 冪等生產者
生產者冪等性可以導致訊息在單個程式中持續存在,從而防止重試問題。啟用冪等性會為每個 Kafka 訊息新增一個生產者 ID (PID) 和一個序列 ID。當代理或客戶端發生故障並嘗試重試時,主題僅接受具有從未見過的生產者和序列 ID 的訊息。代理進一步保證了冪等性,它自動對生產者傳送的所有訊息進行重複資料刪除。
- 2)跨分割槽事務
事務可以確保每條訊息只處理一次。這允許將選定的訊息轉換並原子地寫入多個主題或分割槽,以及偏移量跟蹤消耗的訊息。
原子寫入的狀態由事務協調器和事務日誌(在 Apache Kafka v0.11 中引入)維護。事務協調器類似於消費者組協調器:每個生產者都有一個分配的事務協調器,負責分配PID和管理事務。事務日誌是所有事務的持久記錄,充當事務協調器的狀態儲存。
- 3) 事務消費者
要強制事務消費者只讀取已提交的資料,請將isolation.level 設定為read_committed(預設情況下,隔離級別為未提交讀。)
使用Exactly-Once 訊息傳遞的 Kafka 事務工作流的步驟
下圖捕獲了實現 Exactly-Once Message Delivery 所需的 Kafka 事務工作流步驟。
- 步驟 1 – initTransactions()向事務協調器註冊一個事務transaction ID(一個唯一的永續性生產者 ID)。
- 第 2 步 - 協調器提高生產者 ID 的紀元(確保只有一個合法的生產者活動例項)。不再接受來自該 PID 先前例項的寫入。
- 步驟 3 – 在向分割槽傳送資料之前,生產者使用協調器新增一個新分割槽。
- 步驟 4 – 協調器將每個事務的狀態儲存在記憶體中並將其寫入事務日誌。
- 步驟 5 – 生產者將訊息傳送到分割槽。
- 步驟 6 – 生產者開始提交事務,使協調器啟動其兩階段提交協議。
- 步驟 7 –(提交協議階段 1)協調器通過更新事務日誌來準備提交。
- 步驟 8 –(提交協議階段 2)協調器將事務提交標記寫入事務中涉及的主題分割槽。
- 步驟 9 – 協調器將事務標記為已提交。
- 第 10 步——“Exactly-Once Message Delivery”事務成功。
下面是這個過程的更多技術架構圖:
通過了解 Apache Kafka 如何對資料進行排序並利用上述技術,您可以確保您的資料或應用程式保持良好的工作狀態。
相關文章
- Jetpack Compose的Modifier順序問題Jetpack
- SQL中rownum和order by的執行順序的問題SQL
- 阿里二面:Kafka中如何保證訊息的順序性?這周被問到兩次了阿里Kafka
- SQL Server資料庫調整表中列的順序操作方法及遇到問題SQLServer資料庫
- php與資料庫連線如何實現資料的順序和倒序PHP資料庫
- mysql order by 和 group by 順序問題MySql
- 移動端順序問題上
- 資料結構實驗一:順序表的建立與操作實現、順序表實現約瑟夫環問題資料結構
- 先有雞or先有蛋?淺談資料拆分與特徵縮放的順序問題特徵
- Kafka 如何保證訊息消費的全域性順序性Kafka
- Apache Kafka不是資料庫:資料庫+Kafka=完整ACID - fivetranApacheKafka資料庫
- MySQL:讀取my.cnf的順序問題MySql
- SQL語句中的AND和OR執行順序問題SQL
- TCP協議如何保證資料的順序傳輸TCP協議
- kafka 測試遇到掉資料的問題 nmred/kafka-PHPKafkaPHP
- 順序刷題
- 順序表有序插入資料
- kafka多執行緒順序消費Kafka執行緒
- C++ 順序容器中訪問元素C++
- FrameLayout裡有CardView造成的顯示順序問題View
- Apache Flink 如何正確處理實時計算場景中的亂序資料Apache
- 實際業務處理 Kafka 訊息丟失、重複消費和順序消費的問題Kafka
- 如何在Kafka中將嚴格順序與大規模並行性結合? - EmilKafka並行
- C++輸出流cout的執行順序問題C++
- GROUPBY 和開窗函式執行順序的問題函式
- 如何克服解決Git衝突的恐懼症?(序)Git
- CAD中的物件顯示順序如何設定物件
- kafka 運維中遇到的問題Kafka運維
- 5-順序表查詢及插入問題
- 關於 i=i++ 問題、入棧順序
- python描述器的訪問順序Python
- Apache Kafka資料模型概念簡介 - BaeldungApacheKafka模型
- 不同順序InBoundHandler之間的資料傳遞
- MapStruct與lombok載入順序問題與annotationProcessorPaths的關係?StructLombok
- 一次 RocketMQ 順序消費延遲的問題定位MQ
- spring-kafka多執行緒順序消費SpringKafka執行緒
- Kafka超過保留期限資料未刪除的問題Kafka
- 如何將kafka中的資料快速匯入Hadoop?KafkaHadoop