dotnet core 也能協調分散式事務啦!
2022 年 5 月 24 日,我們發布了 DBPack v0.1.0 版本,該版本主要 release 了分散式事務功能。在我們的規劃里,DBPack 是要支援所有微服務開發語言協調分散式事務的,但經過社區回饋,dotnet core 並不支援。於是,我們在 v0.1.1 對 dotnet core 進行了支援。下面就如何支援 dotnet core 做一個說明。
MySql 協議
先請允許我對 MySql 的通訊協議做一個簡單的介紹。MySql 支援兩種協議,一種是文本(Text)協議,一種是二進位(Binary)協議。MySql 客戶端使用 COM_QUERY 發出的請求,MySql 服務端會以文本協議響應結果;使用 COM_STMT_EXECUTE 命令發出的請求,會以二進位協議響應結果。
在我們用程式調用 MySql Client SDK 發起請求的時候,不同的 MySql Client SDK 會默認使用不同的協議發送請求,但大部分 MySql Client SDK 都支援文本協議和二進位協議,我們可以通過修改屬性配置改變 MySql Client SDK 的默認行為。比如:
- JAVA
@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
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
Dotnet core 如果使用 EntityFrameworkCore 或者 Dapper 來訪問資料庫,目前還不支援使用 Prepared Statement,下面這兩個 issue 有相關說明:
//github.com/dotnet/efcore/issues/5459
//github.com/DapperLib/Dapper/issues/474
在 v0.1.0 版本,我們只對 COM_STMT_EXECUTE 請求做了攔截處理,來協調分散式事務問題。dotnet core 使用 COM_QUERY 提交請求自然無法協調分散式事務,在 v0.1.1 我們增加了 COM_QUERY 請求協調分散式事務的支援,這樣真正做到了支援所有微服務語言協調分散式事務。
dotnet core sample 見://github.com/CECTC/dbpack-samples/tree/main/dotnet。
其他特性
本次發版,還修復了一些 bug,增加了 status api 用於查詢 dbpack 的運行狀態:
$ curl //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
}
至此,我們有了
- /live
- /ready
- /status
- /metrics
這些 api 輔助我們查看 dbpack 的運行狀態。
完整的版本變更日誌請看 //github.com/CECTC/dbpack/releases。
在下一個版本,我們會增加 tracing 和審計日誌的功能。
一些鏈接
DBPack 項目地址://github.com/cectc/dbpack
DBPack 文檔://cectc.github.io/dbpack-doc/#/
DBPack-samples://github.com/cectc/dbpack-samples
DBPack 介紹://mp.weixin.qq.com/s/DmXfk5bAcVYdnOwvp8ocHA
事件驅動的分散式事務架構設計://mp.weixin.qq.com/s/r43JvRY3LCETMoZjrdNxXA