Kafka消費者自動提交配置會導致潛在的重複或資料丟失!

banq發表於2018-12-24

在New Relic,我們使用Apache Kafka構建了管道的一些關鍵部分。多年來,我們遇到了很多問題,並設計了管理Kafka叢集的最佳實踐。我們已經從中學到了很多關於Kafka如何有效而不是那麼有效地工作的知識。
我們遇到的一個基本問題涉及Kafka的消費者自動提交配置 - 特別是當消費者服務遇到記憶體不足(OOM)或其他型別的硬關機時,如何發生資料丟失或資料重複。
讓我解釋一下這種行為及其對Kafka使用者意味著什麼。

問題
生產者傳送給Kafka分割槽的每條訊息都有一個偏移量:用於標識每條訊息的順序索引號。要跟蹤已處理的訊息,您的消費者需要提交已處理訊息的偏移量。
除非您手動觸發提交,否則您最有可能使用Kafka使用者自動提交機制。自動提交是開箱即用的,預設情況下每五秒提交一次。
卡夫卡的消費者不知道你對這個訊息做了什麼,而且對於提交補償更加冷漠。就消費者而言,只要收到訊息,就會被“處理”。
所以現在想象一下,你的消費者已經吸收了1000條訊息並將它們快取到記憶體中。然後自動提交觸發,提交這1,000條訊息的偏移量。但是,假設您的服務現在使用了太多記憶體,並且在處理完所有訊息之前會被OOM終止訊號強行關閉。這樣就永遠不會處理剩餘的可能是數百條訊息,這就是資料丟失。
相反的情況也是可能的。您可以成功處理這1,000條訊息,然後在提交偏移量之前發生問題如硬體故障等。在這種情況下,您將在消費者重新平衡後重新處理另一個例項上的數百條訊息,這就是資料重複。

該怎麼辦呢?
壞訊息是這裡沒有任何簡單的修復。從根本上說,這是一致性保證較弱的問題。所有Kafka使用者想要的只是一次處理 - 保證您只需消費和處理一次訊息。Kafka 0.11版試圖解決這個問題,並使事情略微好轉。可以使用Kafka 0.11編寫一次精確的管道,但要完全消耗一次,您需要在消費者中實現自己的事務語義,以便在完成處理時告訴Kafka(如果出現問題則回滾) 。
此外,在我們的測試中,我們發現Kafka 0.11中訊息生成的事務模型沒有像我們需要的那樣快速處理訊息,每條訊息最多需要10-100毫秒。這是我們無法承受的額外延遲。
不過,你確實還有一些選擇。只要您處於這些框架的限制範圍內,幾個流式解決方案(如FlinkKafka Streams)就可以提供一次性處理。
另一種選擇是“滾動你自己的”一次性策略,它只會自動為已經到達處理管道末尾的訊息提交偏移量。這只是對那些最勇敢的型別的建議,因為這樣做很難,你可能會遇到比你解決的問題更多的問題。

並且始終可以選擇接受資料丟失或重複的風險。可悲的是,這是許多Kafka使用者選擇的選項,但並不總是一個不合理的選擇。您在其中一個場景中實際丟失或重複的資料量相對較小; 自動提交應該只比實際上次提交的訊息少幾秒。發生的頻率也應該很低 - 理想情況下,您的Kafka消費者服務不會獲得通常的OOM終止訊號。
因此,與在您的所有Kafka消費者服務中解決此問題的工程成本相比,如果您使用的資料允許少量損失,這可能只是您所面臨的風險。當然,您始終可以透過構建可靠的服務來降低風險。

向前進
正如我所說,我們在New Relic管理Kafka叢集方面擁有豐富的經驗。我們發現,隨著我們擴充套件以處理大量資料量,構建高度可靠的服務變得更加困難,我們已經就如何處理Kafka中的這一特定缺陷做出了一些實際的決定,如果我們的某個服務經歷過硬關機就執行這些決定。
如果您接受資料丟失的風險,請採取以下步驟將其最小化:

  • 請注意此問題,並將其記錄在風險矩陣中。
  • 確保您的服務穩定。提醒您服務的SIGKILL和OOM。
  • 在構建新服務時,請考慮使用直接解決此問題的流媒體系統。





 

相關文章