「企業事件樞紐」Apache Kafka支持ACID事務嗎?

2019-12-11     首席架構師

我花了很多時間來解釋消息隊列和事件流系統之間的區別。消息隊列系統(如IBM MQ)和事件流系統(如Apache Kafka)之間的最大區別在於流歷史的概念。本質上,在事件流系統中,事件流中的歷史事件在被使用時不會立即刪除。他們呆在。

還有一個主要的區別,那就是交易。事務基本上是一種跨資源保持一致性的方法。在事務系統中,保持事物一致性的硬邏輯是基礎設施的一部分,而不是應用程式的一部分。應用程式在事務的範圍內執行其工作,然後提交事務,在知道事務的所有影響或沒有影響的情況下安全地提交事務。

正如MQ中的主題與Kafka中的主題不太一樣,MQ中的事務也與Kafka中的事務不太一樣。

Kafka確實有一個稱為一次性語義的特性,但是它提供的保證比正確的事務弱得多。它看起來像是API級別的事務,但是如果你仔細觀察,就會發現它是不一樣的。在很多情況下,Kafka保證是足夠的,但是如果您習慣了正確的ACID事務(稍後我將解釋這一點),我將花時間來理解它們之間的區別。

消息傳遞和事務的實踐

讓我們看一些例子。最基本的例子是這樣的:

  1. 開始事務
  2. 使用主題T1中的消息
  3. 向主題T2生成消息
  4. 提交事務

它只是將消息從主題T1移動到主題T2。在事務期間,消息傳遞操作的效果不是永久性的,但是當它提交時,它們都變成永久性的。如果事務失敗,操作都將撤消。

一個更複雜的示例涉及兩個不同的資源管理器,我將使用消息傳遞系統和關係數據庫進行演示。消息傳遞系統用於將數據安全地從一個資料庫轉移到另一個資料庫。

第一個涉及源資料庫和消息傳遞系統的事務如下:

  1. 開始事務
  2. 從源資料庫中讀取行
  3. 生成包含主題T的行數據的消息
  4. 從源資料庫中刪除行
  5. 提交事務

然後,涉及目標資料庫和消息傳遞系統的第二個事務如下:

  1. 開始事務
  2. 使用包含主題T的行數據的消息
  3. 將行插入目標資料庫
  4. 提交事務

對於兩個事務之間的時間段,資料庫中的數據實際上只在消息傳遞系統中。資料庫中的行與消息之間存在精確的一對一關係。這裡的關鍵是,在這兩個事務中,資料庫和消息傳遞系統被協調,以便它們一起提交。這是一個分布式事務的例子,它使用了一種稱為兩階段提交的技術

在這一點上,完全有理由提出這樣的問題:為什麼有人要構建一個基於分布式事務和兩階段提交的系統?當然,這是一種反模式。這是不成比例的,對吧?嗯,可能如此,但是存在許多廣泛使用MQ和資料庫事務的業務應用程式,因為應用程式邏輯非常簡單。常規的應用程式團隊可以實現在系統之間移動數據的神奇壯舉,可能跨越很大的距離,而不會丟失或重複。

IBM MQ可以輕鬆實現這兩個示例。Apache Kafka只能輕鬆地完成第一個任務。如果您是一個完全的專家,那麼您也可以使用一些非常仔細編寫的應用程式代碼來實現第二個目標,以確保在所有情況和故障模式下都沒有數據丟失和重複。這一點也不簡單,我也見過有人嘗試過,但都失敗了。

所以,我的觀點是,用Kafka在技術上是可行的,但它增加了應用程式的複雜性。

消息傳遞和ACID屬性

事務系統實現四個ACID屬性:原子性、一致性、隔離性和持久性。這些概念的定義確實適用於資料庫,但總體思想也適用於消息傳遞系統。大概是這樣的:

  1. 事務表現為單個原子單元,它要麼完全成功,要麼完全失敗
  2. 事務的所有影響都同時對所有觀察者可見
  3. 事務一旦提交,即使在系統出現故障的情況下,它仍然會提交

在IBM MQ中,每個隊列管理器都有一個恢復日誌,所有消息傳遞操作和事務的日誌記錄都被附加到其中。日誌以同步方式寫入磁碟的臨界點相對較慢,但在數據完整性方面有好處。一旦表示事務提交的日誌記錄被寫入日誌,您就知道事務是正確的原子性和持久性的。

在Apache Kafka中,精確的一次語義api是流處理應用程式的強大工具,但是事務保證相對較弱。如果一個事務使用兩個不同的分區,每個分區的負責人負責將操作記錄到自己的日誌中。還有一個內部主題用於記錄整個事務狀態。因此,事務的持久狀態分布在多個日誌和可能的多個伺服器上。如果您研究Kafka中事務提交的設計,它看起來有點像兩階段提交,在事務狀態主題上有準備提交的控制消息,然後在實際主題上有提交標記,最後在事務狀態主題上有提交控制消息。它很聰明,但更脆弱。然後考慮Kafka異步寫入日誌的方式,您會發現Kafka認為提交的事務根本不是原子事務。

在正常的操作下,它會工作得很好,但是不需要太多的想像力就可以想到一個失敗,可以打破酸。例如,如果一個分區複製不足,並且leader遇到意外的斷電,可能會發生少量數據丟失,從而破壞事務的完整性。一個相關的硬故障,比如影響所有代理的停電,甚至可能導致提交/中止標記在所有副本中丟失。您以這樣一種方式部署Kafka,以最小化並希望消除這類問題,但是混合中仍然有異步持久性的元素。

如果存在與消息傳遞系統協調的資料庫等其他資源,那麼這一點尤其重要。我們需要兩個系統的事務保證級別來匹配。一致性和持久性保證必須平等地適用於所有資源。如果事務中的一個參與者在失敗後有點健忘,事務完整性就會丟失。這就是為什麼在與其他資源管理器協調時同步寫入日誌是如此重要的原因;它明確提供了什麼級別的保證,這使得在所有系統上進行匹配變得很容易。

結束

現在您確切地理解了ACID事務和Kafka之間的區別—一次語義(exactly-once-semantics)。如果您不仔細查看現有的代碼,不考慮不同部分需要什麼基本保證,不非常仔細地設計其替換,那麼您就不能選擇一個使用事務的業務應用程式,然後使用Apache Kafka獲得完全相同的結果。您當然可以構建合適的、堅如磐石的業務應用程式,但是您編寫的代碼可能非常不同。例如,您可能選擇允許偶爾的消息複製,以便能夠安全地重試,這可能會帶來對消息的冪等處理。不完全是rock-solid科學,但不同。對於使用Kafka Streams API的流處理應用程式來說,exactly-once semantics 處於最佳狀態,就非常有意義了。

那麼,Apache Kafka做ACID事務嗎?絕對不是。不可能。你能得到類似的效果嗎?如果你以正確的方式設計你的應用程式,是的。這有關係嗎?在很多情況下,並不是這樣,但當它出現時,你絕對不想出錯。只要花點時間去理解您需要的保證,使您的系統可靠,並做出相應的選擇。

原文:https://medium.com/@andrew_schofield/does-apache-kafka-do-acid-transactions-647b207f3d0e

本文:https://pub.intelligentx.net/does-apache-kafka-do-acid-transactions

討論:請加入知識星球【首席架構圈】或者飛聊小組【首席架構師智庫】

文章來源: https://twgreatdaily.com/zh-tw/Z3PN924BMH2_cNUgXfpd.html