DTM是一套跨語言的分散式事務解決方案,支援4種事務模型(Xa、Tcc、事務訊息、Saga),針對分散式事務場景中可能出現的空回滾、懸掛問題,獨創了子事務屏障,在大廠均有應用,但已有的php客戶端只支援tcc,所以重新開發了這個元件。
一、啟動本地dtm
git clone https://github.com/yedf/dtm && cd dtm
go mod download
go run app/main.go dtmsvr
二、安裝客戶端
composer require sett/dtmcli-php
三、示例程式碼
- tcc
特性:一個操作對應2段提交,預處理(try),確認(confirm)、回滾(cancel),確認與回滾不允許失敗。
// 127.0.0.1:36789為dtm預設埠
$trans = new TccTrans("127.0.0.1:36789");
// 獲取新事務ID
$gid = $trans->createNewGid();
// 事務操作
$success = $trans->withOperate($gid, function (TccTrans $tccTrans) use ($baseUrl) {
$result = $tccTrans->callBranch(
["amount" => 30],
"$baseUrl/dtm/tcc/transOut",
"$baseUrl/dtm/tcc/transOutConfirm",
"$baseUrl/dtm/tcc/transOutCancel"
);
if (!$result) {
echo "call branch fail\n";
return false;
}
return $tccTrans->callBranch(
["amount" => 30],
"$baseUrl/dtm/tcc/transIn",
"$baseUrl/dtm/tcc/transInConfirm",
"$baseUrl/dtm/tcc/transInCancel"
);
});
- saga
特性:一個操作對應1個回滾,任何一個失敗,整個事務視為失敗,回滾。
$trans = new SagaTrans("127.0.0.1:36789");
$gid = $trans->createNewGid();
$trans
->withGid($gid)
->withOperate("$baseUrl/dtm/saga/transOut", "$baseUrl/dtm/saga/transOutRevert", ["amount" => 30])
->withOperate("$baseUrl/dtm/saga/transIn", "$baseUrl/dtm/saga/transInRevert", ["amount" => 30]);
$success = $trans->submit();
- 事務訊息
特性:操作對應一個查詢。
$trans = new MsgTrans("127.0.0.1:36789");
$gid = $trans->createNewGid();
$trans
->withOperate("$baseUrl/dtm/msg/transOut", ["amount" => 30])
->withOperate("$baseUrl/dtm/msg/transIn", ["amount" => 30])
->withQueryUrl("$baseUrl/dtm/msg/query")
->prepare();
$success = $trans->submit();
- 子事務屏障
特性:防止空回滾,處理懸掛,冪等等問題。
class UserDatabase implements IDatabase
{
public function execute(string $query) {
// TODO: Implement execute() method.
}
public function query(string $query): bool {
// TODO: Implement query() method.
}
public function rollback() {
// TODO: Implement rollback() method.
}
public function commit() {
// TODO: Implement commit() method.
}
}
$baseUrl = "http://127.0.0.1:18310";
try {
$trans = new BarrierTrans([
"trans_type" => "tcc",
"gid" => "ac130059_4pQHea5Xtsq",
"op" => "prepare",
"branch_id" => "01"
]);
$database = new UserDatabase();
$success = $trans->call($database, function (IDatabase $database) {
// 使用當前資料庫連線操作,保證所有操作都在一個本地事務中
// do what you want...
return true;
});
echo "transaction result {$success}";
} catch (Exception $exception) {
var_dump($exception->getTraceAsString());
echo "exception with error " . $exception->getMessage();
}
- Xa
特性:基於資料庫本地事務,保證操作在同一個事務中,使用的場景比較少,不寫了
本作品採用《CC 協議》,轉載必須註明作者和本文連結