雙重寫入:如何解決微服務分散式系統中資料不一致? - Thorben
由於許多新應用程式是作為微服務系統構建的,因此雙重寫入已成為一個普遍的問題。它們是導致資料不一致的最常見原因之一。更糟的是,許多開發人員甚至都不知道雙重寫入是什麼。
什麼是雙重寫入?
雙重寫入描述了您在兩個個系統(例如資料庫和Apache Kafka)中更改資料時的情況,而沒有額外的層來確保兩個服務上的資料一致性。
只要兩個操作都成功,一切就OK了。即使第一筆交易失敗,也還是可以的。但是,如果您成功提交了第一筆交易而第二筆交易失敗,則說明您遇到了問題。您的系統現在處於不一致狀態,沒有容易修復的方法。
分散式事務不再是一種選擇
過去,當我們構建整體/.單體/Monolith時,我們使用分散式事務來避免這種情況。分散式事務使用兩階段提交協議。它將事務的提交過程分為兩個步驟,並確保所有系統的ACID原則。
但是,如果我們要構建微服務系統,則不會使用分散式事務。這些交易需要鎖,並且無法很好地擴充套件。他們還需要所有涉及的系統同時啟動和執行。
那你該怎麼辦呢?
3個無效的“解決方案”
當我在會議演講中或在一個研討會上與與會者討論此主題時,我經常聽到以下3條建議之一:
- 是的,我們知道此問題,我們沒有解決方案。但這還不錯。到目前為止,什麼都沒有發生。讓我們保持原樣。
- 讓我們將與Apache Kafka的互動移動到提交後監聽器。
- 在提交資料庫事務之前,讓我們將事件寫入Kafka中的主題。
好吧,很明顯,建議1的風險很大。它可能在大多數時間都有效。但是遲早,您將在服務儲存的資料之間建立越來越多的不一致之處。
因此,讓我們集中討論選項2和3。
2. 在提交後監聽器中釋出事件
在提交後監聽器中釋出事件是一種非常流行的方法。它確保僅在資料庫事務成功時才釋出事件。但是,很難解決Kafka崩潰或任何其他原因阻止您釋出事件的情況。
您已經提交了資料庫事務。因此,您無法輕鬆地還原這些更改。當您嘗試在Kafka中釋出事件時,其他事務可能已經使用並修改了該資料。
您可能會嘗試將故障保留在資料庫中,並執行常規的清理作業以嘗試恢復失敗的事件。這可能看起來像是一個合理的解決方案,但是它有一些缺陷:
- 僅當您可以將失敗的事件保留在資料庫中時,它才有效。如果資料庫事務失敗,或者您的應用程式或資料庫崩潰,然後才能儲存有關失敗事件的資訊,則將丟失它。
- 僅當事件本身沒有引起問題時,它才起作用。
- 如果在清除作業恢復失敗的事件之前,另一個操作為該業務物件建立了一個事件,則事件將混亂。
這些似乎是假設的情況,但這就是我們正在準備的事情。本地事務,分散式事務和確保最終一致性的方法的主要思想是,絕對要確保您不會造成任何(永久)不一致。
提交後偵聽器無法確保這一點。因此,讓我們看一下其他選項。
3. 在提交資料庫事務之前釋出事件
在討論了為何提交後監聽器不起作用之後,通常會建議使用這種方法。如果在提交之後釋出事件會導致問題,您只需在提交事務之前釋出它,對嗎?
好吧,不……讓我解釋一下……
如果您無法釋出事件,則在提交事務之前釋出事件使您可以回滾事務。那就對了。
但是,如果資料庫事務失敗,該怎麼辦?
您的操作可能違反唯一約束,或者同一資料庫記錄上可能有2個併發更新。提交期間將檢查所有資料庫約束,並且不能確保它們都不會失敗。資料庫事務也彼此隔離,因此如果不使用鎖,就無法阻止併發更新。但這帶來了新的可伸縮性問題。簡而言之,您的資料庫事務可能會失敗,並且您無能為力,或者對此無能為力。
如果發生這種情況,則您的活動已經發布。其他微服務可能已經觀察到它並觸發了一些業務邏輯。您無法撤回活動。
如前所述,撤消操作失敗的原因相同。您也許可以構建一個大多數情況下都可以使用的解決方案。但是您無法建立絕對安全的東西。
如何避免雙重寫入?
您可以選擇幾種方法來避免雙重寫入。但是您需要知道,如果不使用分散式事務,則只能構建最終一致的系統。
總體思路是將流程分為多個步驟。這些步驟中的每個步驟僅適用於一個資料儲存,例如資料庫或Apache Kafka。這使您能夠使用本地事務,所涉及系統之間的非同步通訊以及非同步的,可能無限的重試機制。
如果您只想在服務之間複製資料或通知其他服務已發生事件,則可以將發件箱模式與Debezium等變更資料捕獲實現一起使用。我在以下文章中詳細解釋了這種方法:
而且,如果您需要實施涉及多個服務的一致的寫入操作,則可以使用SAGA模式。我將在以下文章之一中對其進行詳細說明。
結論
雙重寫入常常被低估,許多開發人員甚至都不知道潛在的資料不一致。
如本文所述,在沒有分散式事務或確保最終一致性的演算法的情況下,寫入2個或更多系統可能會導致資料不一致。如果使用多個本地事務,則無法處理所有錯誤情況。
避免這種情況的唯一方法是將通訊分為多個步驟,並且在每個步驟中僅寫入一個外部系統。SAGA模式和變更資料捕獲實現(例如Debezium)使用這種方法來確保對多個系統的一致寫入操作或將事件傳送到Apache Kafka。
相關文章
- 如何解決分散式系統中的“幽靈復現”?分散式
- 「和耳朵」聊聊微服務與分散式系統微服務分散式
- 如何解決 Windows 和 Manjaro 雙系統時間不一致WindowsJAR
- 如何在微服務分散式架構中刪除資料? - bennorthrop微服務分散式架構
- 隨行付微服務之分散式檔案系統微服務分散式
- 分散式系統(三)——分散式事務分散式
- 分散式系統的資料一致性問題,你是如何解決的分散式
- 分散式與微服務分散式微服務
- 分散式系統(Distributed System)資料分散式
- 分散式訊息系統如何解決訊息的順序&重複兩大硬傷?分散式
- 微服務架構及分散式事務解決方案微服務架構分散式
- 分散式系統中資料儲存方案實踐分散式
- 比較微服務中的分散式事務模式微服務分散式模式
- 竹雲&巨杉資料庫:基於分散式資料庫打造微服務架構身份管理與訪問控制系統解決方案資料庫分散式微服務架構
- 分散式/微服務必配APM系統,SkyWalking讓你不迷路分散式微服務
- 分散式系統中的事務問題分散式
- 微服務架構中的分散式事務全面詳解 -DZone微服務微服務架構分散式
- 分散式系統2:分散式系統中的時鐘分散式
- ZooKeeper分散式專題與Dubbo微服務入門分散式微服務
- Calvin:分割槽資料庫系統的快速分散式事務資料庫分散式
- 微服務分散式事務4種解決方案實戰微服務分散式
- 分散式資料庫系統(DDBS) 概述分散式資料庫
- 分散式系統中的資料儲存方案實踐分散式
- 快取與資料庫雙寫,不一致問題及解決方案快取資料庫
- 如何解決微服務之間的資料依賴問題?微服務
- spring cloud微服務分散式雲架構-Spring Cloud 分散式的五大重點SpringCloud微服務分散式架構
- windows平臺的分散式微服務解決方案(4)--資料庫的讀寫分離Windows分散式微服務資料庫
- PHP 微服務之 [分散式事務]PHP微服務分散式
- PHP 微服務之【分散式事務】PHP微服務分散式
- 【大資料】BigTable分散式資料儲存系統分散式資料庫 | 複習筆記大資料分散式資料庫筆記
- spring cloud微服務分散式雲架構-Gateway入門SpringCloud微服務分散式架構Gateway
- 微服務架構下分散式事務解決方案-hoop(一)微服務架構分散式OOP
- 微服務分散式事務解決方案-開源軟體seata微服務分散式
- 又出現異常資料?來剖析一下分散式系統中的「事務」分散式
- 大資料分散式計算系統 Spark 入門核心之 RDD大資料分散式Spark
- 微服務之分散式配置中心微服務分散式
- 大資料 | 分散式檔案系統 HDFS大資料分散式
- DTM:Golang中微服務架構的分散式事務框架Golang微服務架構分散式框架