跨系統數據一致性問題經驗實戰

目前隨着微服務化建設的普及,存在越來越多的跨系統數據交互情況,跨系統數據一致性問題越發凸顯,那如何有效保證跨系統數據的一致性呢?

本文旨在總結沉澱工作中問題的解決經驗,整理解決跨系統數據不一致問題的經驗方法。

1、爲什麼會有跨系統數據一致性問題?

提到數據一致性,我們很容易想到的就是數據庫中的事務操作。

事務的原子性和持久性可以確保在一個事務內,操作多條數據,要麼都成功,要麼都失敗。這樣在一個系統內部,我們可以很自然地使用數據庫事務來保證數據一致性。但是在微服務的今天,一項操作會涉及到跨多個系統多個數據庫的時候,用單一的數據庫事務就沒辦法解決了。

另外常見的一種情況就是:存在依賴情況的系統服務,例如業務端與用戶端(業務端負責生產數據,用戶端負責展示數據),需要數據同步來保障跨系統服務的數據一致性,很多時候採用何種數據同步方式,來保障數據應用的時效性至關重要。

2、一致性問題的難點分析

爲了更好的描述和理解問題,我們用一個案例來闡述:

假設存在訂單系統與庫存系統,在實際業務中訂單的創建會伴隨着庫存的減少。兩個系統爲微服務化部署,其應用數據也存放在獨立的數據庫中,兩個系統間通過網絡進行通信。

2.1 CAP 原則

CAP 指的是 Consistency(一致性)、Availability(可用性)、Partition tolerance(分區容錯性)。

放棄 A (可用性)來保障 CP

具體表現爲產生通信故障後,應用會進入阻塞狀態,一直嘗試與庫存系統恢復通信直到完成所有數據處理。這種方案是優先保障數據完整性,但此方案用戶體驗極差,因爲在所有操作完成前用戶會一直處於等待的狀態。

CAP 本身就是互斥的,只能從三者中選兩個,對於 CA、AP、CP 都有它們自己的應用場景,要結合實際進行選擇。

CAP 原則在實際項目中的運用,對於互聯網應用來說,如果爲了用戶體驗完全放棄數據一致性這也是不可取的,畢竟數據纔是應用的根本。

那該怎麼解決呢?

保障最終一致性的措施有很多,主要包括:分佈式事務和 TCC 一致性方案。

MySQL 其實有一個兩階段提交的分佈式事務方案(MySQL XA),但是該方案存在嚴重的性能問題。

比如,一個數據庫的事務與多個數據庫之間的 XA 事務性能可能相差 10 倍。另外,在 XA 的事務處理過程中它會長期佔用鎖資源,所以一開始我們並不考慮這個方案。

在此,我們主要討論一下 TCC 一致性方案。

2.2 TCC 一致性方案

TCC 是一種數據一致性方案,我們會把原來的一個接口分爲三個接口:

在 TCC 中,它將分佈式處理過程分爲兩個階段:

1、Try 是第一個階段,用於嘗試並鎖定資源;

2、如果資源鎖定成功,第二個階段開始進行 Confirm 提交完成數據操作;

3、如果資源鎖定失敗,第二個階段就會進行 Cancel 將數據回滾;

TCC 實施過程中有哪些注意事項呢?

1)在 Try 階段做盡可能多的事情

要把絕大多數的業務邏輯在 Try 階段完成,因爲 TCC 設計之初認爲 Confirm 或 Cancel 是一定要成功的,因此不要二階段包含任何業務代碼或者遠程通信,只通過最簡單的代碼釋放凍結資源。

2)保障 Confirm 或 Cancel 執行成功

假如 Confirm 或 Cancel 執行時出現錯誤,那具體應用時也會不斷重試執行操作來儘量保證執行成功,這個過程中可能會多次執行 update 語句,因此要注意代碼的冪等性。

3)Confirm 或 Cancel 執行失敗的兜底方案

極小概率下,Confim 或 Cancel 在多次重試後宣告失敗,便會出現數據最終不一致的情況,這就需要自己開發額外的數據完整性校驗程序補救或者通過人工進行補錄。

TCC 歸根結底是一種理論設計,需要廠商實現相應的框架給予支撐。

在 Java 開源領域著名的 TCC 框架有:ByteTCC、Hmily、Tcc-transaction 與 Seata。

3、有效數據同步方案實踐

問題描述:我們還是以之前的案例場景,數據需要從訂單系統同步到庫存系統中。

解決數據一致性常用的三類數據同步方案:實時同步、定時同步、手動同步。

3.1 實時同步

實時同步可以從數據庫、應用處理兩個層面來解決。

3.1.1 數據庫層面

通用採用數據庫的數據同步,主從解決,當 master(主) 庫的數據發生變化的時候,變化會實時的同步到 slave(從) 庫。

優勢:

如何實現主從一致

關於 MySQL 主從複製主要同步的是 binlog 日誌,涉及到三個線程,一個運行在主節點(log dump thread),其餘兩個 (I/O thread, SQL thread) 運行在從節點,如下圖所示:

(1)主節點 binary log dump 線程

當從節點連接主節點時,主節點會創建一個 log dump 線程,用於發送 binlog 的內容。在讀取 binlog 中的操作時,此線程會對主節點上的 binlog 加鎖,當讀取完成,在發送給從節點之前,鎖會被釋放。

(2)從節點 I/O 線程

當從節點上執行 start slave 命令之後,從節點會創建一個 I/O 線程用來連接主節點,請求主庫中更新的 binlog。I/O 線程接收到主節點 binlog dump 進程發來的更新之後,保存在本地 relay-log(中繼日誌)中。

(3)從節點 SQL 線程

SQL 線程負責讀取 relay log 中的內容,解析成具體的操作並執行,最終保證主從數據的一致性。

3.1.2 API 調用

一次業務數據操作,需要調用多方 API 實現實時數據的同步。

劣勢比較明顯,主要表現在:

1)處理耗時長,需要串行調用多方 API 並等待響應,用戶體驗較差;

2)會有一定幾率出現數據不一致情況(個別 API 調用出錯、未響應等情況)。

3.2 異步同步

3.2.1 異步消息隊列

Message Queue(MQ),消息隊列中間件

MQ 通過將消息的發送和接收分離來實現應用程序的異步和解偶,同時 MQ 屏蔽底層複雜的通訊協議,定義了一套應用層的、更加簡單的通訊協議。

應用 MQ 的優點:解耦,削峯,數據分發。

在業務系統設計中,我們常常會存在一個平臺系統 A,它關聯同步了許許多多的系統的對接(系統 B、C、D 等)。

利用 MQ 可以很好的解決系統對接和數據同步問題,同時可以忽略對接系統的穩定性等訴求。

3.2.2 定時同步

定時任務在系統中並不少見,主要目的是用於需要定時處理數據或者執行某個操作的情況下,如定時關閉訂單,或者定時備份。

常見的定時任務分爲 2 種:

1)第一種:固定時間執行,保障同步並校準數據

如:每分鐘執行一次,每天執行一次。

2)第二種:延時多久執行,即動作發生後,定時多久後執行任務

如:15 分鐘後關閉訂單付款狀態,24 小時候後關閉訂單並且釋放庫存等。

3.3 手動同步

在一般數據管理中,在具備了上述實時同步和異步同步的情況下,爲了防止其他異常情況造成的數據不一致,可以考慮開發備用數據同步工具(腳本)來手動方式主動進行恢復,將數據同步並進行校準。

其優劣也很明顯,優勢:隨時隨地主動操作;劣勢:需要人工進行干預。

數據同步最好的情況是能夠實現實時同步,但是考慮到數據同步過程中對系統的壓力以及數據實時同步的必要性等因素有時會選擇定時同步和手動同步。

4、應用經驗總結

技術還是要解決實際問題來落地。應用場景很關鍵,不要單純爲了技術而技術,技術歸根結底還是爲應用場景和產業落地服務。軟件設計過程中,不需要刻意去應用看起來高大上的解決方案,而當需要引入時,要同時考慮開發、維護成本以及對應性能的提升的性價比,否則得不償失。

1、任何架構方案都是不斷演進的

任何數據同步本身沒有優劣之分,都有其適合的應用場景。

2、架構的目的是解決業務問題

能夠解決當前問題的架構方案,同時兼具易於擴展及維護,那就是一個優秀的架構。

隨着互聯網的告訴發展,跨系統數據一致性應用需求一定會越來越迫切,跨地域跨系統場景的真正痛點也會越來越清晰,希望我們在跨系統數據一致性方面的調研和探索可以給大家一個思路和參考。

來源:

https://www.toutiao.com/article/7096379657804661263/?log_from=45754430e9de7_1652403929490

本文由 Readfog 進行 AMP 轉碼,版權歸原作者所有。
來源https://mp.weixin.qq.com/s/LGKl2Tve1ENdrU85RUgxZg