中國電子云資料庫 Mesh 項目 DBPack 的實踐
作者:劉曉敏
2022 年 4 月,中國電子云開源了其雲原生資料庫 Mesh 項目 DBPack。該項目的誕生,旨在解決用戶上雲過程中面臨的一些技術難點,諸如分散式事務、分庫分表等。由於它資料庫 Mesh 的定位,意味著它可以支援任意微服務程式語言。
分散式事務
DBPack 的分散式事務致力於實現對用戶的業務無入侵,它對 HTTP 流量和 MYSQL 流量做了攔截代理,支援 AT 模式(自動補償 SQL)和 TCC 模式(自動補償 HTTP 請求)。
DBPack 從 Kubernetes control loop 思想中獲得靈感,採用 ETCD Watch 機制來驅動分散式事務提交回滾。在採用代理使連接增加一跳的情況下,它的性能相比採用 MYSQL 存儲的分散式事務解決方案 seata-golang 性能提高了百分之 50。
AT 模式
AT 模式的性能取決於全局鎖的釋放速度,哪個事務競爭到了全局鎖就能對業務數據做修改,在單位時間內,全局鎖的釋放速度越快,競爭到鎖的事務越多,性能越高。從 ETCD 官方 Bench 測試數據中可以看到,ETCD 在高並發下,讀寫延遲很低,不同並發壓力下寫延遲 2 毫秒到 20 毫秒不等,讀延遲基本在 10 毫秒以內。採用 ETCD 來存儲全局鎖是 DBPack 分散式事務性能提升的關鍵。
上圖展示了 seata-golang 協調一個分散式事務的交互邏輯。從圖上我們可以看出,事務發起者(TM)和事務協調者(TC)間存在創建(開始)全局事務、提交(回滾)全局事務 RPC 交互。事務參與者(RM)和事務協調者(TC)間存在註冊分支事務、報告分支事務執行狀態 RPC 交互。事務協調者(TC)和 MYSQL 交互保存狀態數據。
而 DBPack 創建全局事務、註冊分支事務只是在 ETCD 插入兩條 KV 數據,事務提交回滾時修改對應數據的狀態,DBPack Sidecar 通過 ETCD Watch 機制感知到數據的變化就能立即處理數據的提交回滾,從而在交互上減少了很多 RPC 請求。
各 Sidecar Watch 應用產生的數據,各自處理,實際上已經沒有中心化的事務協調者,架構也變得簡單了。核心的事務協調邏輯程式碼包括配置程式碼都比 Seata-golang 大幅減少。所以 DBPack 以全新的雲原生的思路,帶了更簡潔的架構和更高的性能。
DBPack 支援所有微服務程式語言,samples 中已提供了 Go 語言和 Java 語言的例子,PHP 和 Python 的例子也在開發中。
TCC 模式
提到 TCC 模式,大家可能第一時間想到 TCC 模式可能存在的問題:冪等性、防懸掛等。事務懸掛產生的原因是什麼?其實這是一個很偽的問題!
APP1 在調用 APP2 的 Prepare 方法之前,事務框架根據上下文資訊,自動把 Commit、Cancel 需要執行的方法名以及 Prepare 方法執行的上下文告訴事務協調者(註冊分支事務),再執行 Prepare 方法。如果執行 APP1 調用 APP2 的 Prepare 方法的時候,發生網路問題,導致 APP2 遲遲沒有收到 Prepare 請求,事務協調者經過一定時間後,認為全局事務超時,則 TC 根據註冊上來的事務分支資訊發起全局回滾,此時,APP1 向 APP2 發起一個 Cancel 請求,很巧的是,APP2 端 Cancel 請求比 Prepare 請求先到達,事務空回滾後,再收到 Prepare 請求,Prepare 如果正常執行了,那就完了,全局事務已經回滾了,這個 Prepare 操作永遠也不會提交、回滾,事務掛起了,數據不一致了。
首先,這種概率很小,其次,為什麼一定要在 Prepare 網路請求之前註冊分支事務,可不可以在 APP2 收到 Prepare 請求執行業務程式碼之前註冊,這時候一定能確定 Prepare 請求已經到了,Cancel 請求確定能在 Prepare 請求之後發生,是不是就不存在懸掛問題了。
實際上 seata-golang 誕生之時就支援在分支業務執行端註冊 TCC 事務分支,但大家可能沒有深入思考這個問題,機械地認為事務懸掛必然會發生。
DBPack 也是在請求到達 sidecar 後再註冊 TCC 事務分支,確保 Prepare 先於 Cancel 執行。有人說因為 CPU 調度的原因,還是可能出現 Cancel 先於 Prepare 執行的情況,但這種概率非常非常低。具體到操作的業務數據,建議使用 XID 和 BranchID 加鎖。
讀寫分離
DBPack 當前支援對 SQL 請求自動路由,寫請求路由到寫庫,讀請求路由到讀庫。在開啟事務的情況下,請求自動路由到寫庫。同時,也可以通過 SQL Hint 自動路由讀請求到用戶指定的資料庫。
分庫分表
分庫分表的功能目前還在開發中,當前已經支援跨分片、跨 DB 的查詢請求,支援 Order By 和 Limit。
結語
更多特性我們也在積極開發中,DBPack 社區非常 Open,進入到社區我們都是平等的開源愛好者,在這裡你也可以成長為大佬,歡迎感興趣的同學與我們一起建設 DBPack 社區。進群或參與社區建設請添加微信:scottlewis。
鏈接
DBPack 項目地址://github.com/cectc/dbpack
DBPack 文檔://cectc.github.io/dbpack-doc/#/