基於Dtm分散式事務管理的php客戶端

失色天空發表於2021-12-12

DTM是一套跨語言的分散式事務解決方案,支援4種事務模型(Xa、Tcc、事務訊息、Saga),針對分散式事務場景中可能出現的空回滾、懸掛問題,獨創了子事務屏障,在大廠均有應用,但已有的php客戶端只支援tcc,所以重新開發了這個元件。

一、啟動本地dtm

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 協議》,轉載必須註明作者和本文連結

相關文章