2022 年 5 月 24 日,我們釋出了 DBPack v0.1.0 版本,該版本主要 release 了分散式事務功能。在我們的規劃裡,DBPack 是要支援所有微服務開發語言協調分散式事務的,但經過社群反饋,dotnet core 並不支援。於是,我們在 v0.1.1 對 dotnet core 進行了支援。下面就如何支援 dotnet core 做一個說明。
先請允許我對 MySql 的通訊協定做一個簡單的介紹。MySql 支援兩種協定,一種是文字(Text)協定,一種是二進位制(Binary)協定。MySql 使用者端使用 COM_QUERY 發出的請求,MySql 伺服器端會以文字協定響應結果;使用 COM_STMT_EXECUTE 命令發出的請求,會以二進位制協定響應結果。
在我們用程式呼叫 MySql Client SDK 發起請求的時候,不同的 MySql Client SDK 會預設使用不同的協定傳送請求,但大部分 MySql Client SDK 都支援文字協定和二進位制協定,我們可以通過修改屬性設定改變 MySql Client SDK 的預設行為。比如:
@Mapper
public interface ProductMapper {
@Update("UPDATE /*+ XID('${xid}') */ `product`.`inventory` SET `available_qty` = `available_qty` - #{qty}, allocated_qty = allocated_qty + #{qty} WHERE product_sysno = #{productSysNo} AND available_qty >= #{qty}")
boolean allocateInventory(@Param("xid") String xid, @Param("productSysNo") long productSysNo, @Param("qty") int qty);
}
在 java 語言編寫的微服務中,我們寫了一個方法去修改商品的庫存,當我們傳入引數提交執行的時候,預設該 SQL 請求會被編碼成
update /*+ XID('gs/aggregationSvc/81336085455405058') */ product.inventory set available_qty = available_qty - 2, allocated_qty = allocated_qty + 2 where product_sysno = 1 and available_qty >= 2;
通過 COM_QUERY 命令發出。
我們可以通過修改連線字串,在原來的 jdbc:mysql://dbpack2:13307/product
上加上 useServerPrepStmts=true
,改為 jdbc:mysql://dbpack2:13307/product?useServerPrepStmts=true
,再次執行時,會首先發出 COM_STMT_PREPARE 請求:
UPDATE /*+ XID('gs/aggregationSvc/2612341069705662465') */ product.inventory set available_qty = available_qty - ?, allocated_qty = allocated_qty + ? WHERE product_sysno = ? and available_qty >= ?
獲取到 statement id 後,再將 statement id 和請求引數編碼後通過 COM_STMT_EXECUTE 命令發出。
Golang MySql driver 預設是以二進位制協定傳送帶引數的 DML 請求的,通過在 dsn 上加上引數 interpolateParams=true
,才會以文字協定傳送。例如:
dksl:123456@tcp(127.0.0.1:13306)/employees?interpolateParams=true&timeout=10s&readTimeout=10s&writeTimeout=10s&parseTime=true&loc=Local&charset=utf8mb4,utf8
Dotnet core 如果使用 EntityFrameworkCore 或者 Dapper 來存取資料庫,目前還不支援使用 Prepared Statement,下面這兩個 issue 有相關說明:
https://github.com/dotnet/efcore/issues/5459
https://github.com/DapperLib/Dapper/issues/474
在 v0.1.0 版本,我們只對 COM_STMT_EXECUTE 請求做了攔截處理,來協調分散式事務問題。dotnet core 使用 COM_QUERY 提交請求自然無法協調分散式事務,在 v0.1.1 我們增加了 COM_QUERY 請求協調分散式事務的支援,這樣真正做到了支援所有微服務語言協調分散式事務。
dotnet core sample 見:https://github.com/CECTC/dbpack-samples/tree/main/dotnet。
本次發版,還修復了一些 bug,增加了 status api 用於查詢 dbpack 的執行狀態:
$ curl http://localhost:9999/status
$ {
"listeners": [{
"protocol_type": "mysql",
"socket_address": {
"address": "0.0.0.0",
"port": 13306
},
"active": true
}],
"distributed_transaction_enabled": true,
"is_master": true
}
至此,我們有了
這些 api 輔助我們檢視 dbpack 的執行狀態。
完整的版本變更紀錄檔請看 https://github.com/CECTC/dbpack/releases。
在下一個版本,我們會增加 tracing 和審計紀錄檔的功能。
DBPack 專案地址:https://github.com/cectc/dbpack
DBPack 檔案:https://cectc.github.io/dbpack-doc/
DBPack-samples:https://github.com/cectc/dbpack-samples
DBPack 介紹:https://mp.weixin.qq.com/s/DmXfk5bAcVYdnOwvp8ocHA
事件驅動的分散式事務架構設計:https://mp.weixin.qq.com/s/r43JvRY3LCETMoZjrdNxXA