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 有相關說明:

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
}

至此,我們有了

  • /live
  • /ready
  • /status
  • /metrics

這些 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

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章