DTM は 2021 年 6 月 4 日からバージョン 0.1 をリリースし、急速に発展しています |
|
上記で比較した特徴から判断すると、DTM には多くの点で大きな利点があります。複数言語のサポートと複数のストレージ エンジンのサポートを考慮する場合、DTM が最初の選択肢となることは間違いありません。
インストール
dtm-client をインストールすると非常に便利です。 Composer 経由
composer require dtm/dtm-client
- DTM サーバーを使用するときは忘れずに起動してください
Configuration
##構成ファイル
Hyperf フレームワークを使用している場合は、コンポーネントをインストールした後、次の vendor:publish
コマンドを使用して、./config に構成ファイルを公開できます。 /autoload/dtm.php
php bin/hyperf.php vendor:publish dtm/dtm-client
Hyperf 以外のフレームワークで使用している場合は、./vendor/dtm/dtm-client/publish/dtm.php をコピーできます。
ファイルを対応する構成ディレクトリの中央にコピーします。
use DtmClient\Constants\Protocol;
use DtmClient\Constants\DbType;
return [
// 客户端与 DTM Server 通讯的协议,支持 Protocol::HTTP 和 Protocol::GRPC 两种
'protocol' => Protocol::HTTP,
// DTM Server 的地址
'server' => '127.0.0.1',
// DTM Server 的端口
'port' => [
'http' => 36789,
'grpc' => 36790,
],
// 子事务屏障配置
'barrier' => [
// DB 模式下的子事务屏障配置
'db' => [
'type' => DbType::MySQL
],
// Redis 模式下的子事务屏障配置
'redis' => [
// 子事务屏障记录的超时时间
'expire_seconds' => 7 * 86400,
],
// 非 Hyperf 框架下应用子事务屏障的类
'apply' => [],
],
// HTTP 协议下 Guzzle 客户端的通用配置
'guzzle' => [
'options' => [],
],
];
ミドルウェアの構成
使用前に、DtmClient\Middleware\DtmMiddleware
を構成する必要があります。このミドルウェアはサーバーのグローバル ミドルウェアとして使用され、ミドルウェアはサーバーのグローバル ミドルウェアとして使用されます。 PSR-15 仕様。この仕様をサポートするすべてのフレームワークに適用されます。
Hyperf でのミドルウェア構成については、「Hyperf ドキュメント - ミドルウェア」の章を参照してください。
使用方法
dtm-client の使用は非常に簡単で、誰もがよりよく理解してデバッグできるように、サンプル プロジェクト dtm-php/dtm-sample が提供されています。
このコンポーネントを使用する前に、より詳細な理解のために公式 DTM ドキュメントを読むことも強くお勧めします。
TCC モード
TCC モードは、非常に人気のある柔軟なトランザクション ソリューションであり、それぞれ Try-confirm-Cancel の頭字語で構成されています。この概念は Pat Helland によって最初に提案されました。 2007 年に出版された「分散トランザクションを超えた生活: 背教者の意見」というタイトルの論文で述べられています。
TCC の 3 つのフェーズ
試行フェーズ: 実行を試み、すべてのビジネス チェックを完了し (一貫性)、必要なビジネス リソースを確保する (準分離)
確認ステージ: すべてのブランチの Try が成功した場合は、確認ステージに進みます。確認は、業務チェックを行わずに実際に業務を実行し、Try フェーズで予約されたビジネス リソースのみを使用します。
Cancel フェーズ: すべてのブランチの Try の 1 つが失敗した場合、Cancel フェーズに移行します。キャンセルすると、試行フェーズ中に予約されたビジネス リソースが解放されます。
銀行間送金と同様のビジネスを実行したい場合、送金 (TransOut) と送金 (TransIn) は別のマイクロサービスにあります。正常に完了した TCC トランザクションの一般的なシーケンス図は次のとおりです。 :
コード例
以下は、Hyperf フレームワークでの使用方法を示しています。他のフレームワークも同様です。
<?php
namespace App\Controller;
use DtmClient\TCC;
use DtmClient\TransContext;
use Hyperf\Di\Annotation\Inject;
use Hyperf\HttpServer\Annotation\Controller;
use Hyperf\HttpServer\Annotation\GetMapping;
use Throwable;
#[Controller(prefix: '/tcc')]
class TccController
{
protected string $serviceUri = 'http://127.0.0.1:9501';
#[Inject]
protected TCC $tcc;
#[GetMapping(path: 'successCase')]
public function successCase()
{
try {
$this->tcc->globalTransaction(function (TCC $tcc) {
// 创建子事务 A 的调用数据
$tcc->callBranch(
// 调用 Try 方法的参数
['amount' => 30],
// Try 方法的 URL
$this->serviceUri . '/tcc/transA/try',
// Confirm 方法的 URL
$this->serviceUri . '/tcc/transA/confirm',
// Cancel 方法的 URL
$this->serviceUri . '/tcc/transA/cancel'
);
// 创建子事务 B 的调用数据,以此类推
$tcc->callBranch(
['amount' => 30],
$this->serviceUri . '/tcc/transB/try',
$this->serviceUri . '/tcc/transB/confirm',
$this->serviceUri . '/tcc/transB/cancel'
);
});
} catch (Throwable $e) {
var_dump($e->getMessage(), $e->getTraceAsString());
}
// 通过 TransContext::getGid() 获得 全局事务ID 并返回
return TransContext::getGid();
}
}
Saga パターン
Saga パターンは、分散トランザクションの分野で最も有名なソリューションの 1 つであり、主要なシステムでも非常に人気があります。Hector Garcaa-Molrna によって出版された論文 SAGAS に初めて登場しました。ケネス・セイラム、1987年。
Saga は、結果的に整合性のあるトランザクションであり、長時間実行トランザクション (Long-running-transaction) とも呼ばれる柔軟なトランザクションであり、一連のローカル トランザクションで構成されます。各ローカル トランザクションがデータベースを更新した後、メッセージまたはイベントを発行して、Saga グローバル トランザクション内の次のローカル トランザクションの実行をトリガーします。一部のビジネス ルールを満たすことができないためにローカル トランザクションが失敗した場合、Saga は、失敗したトランザクションの前に正常にコミットされたすべてのトランザクションに対して補償操作を実行します。したがって、Saga モードと TCC モードを比較すると、リソース予約手順が不足しているため、ロールバック ロジックの実装がより困難になることがよくあります。
佐賀サブトランザクション分割
たとえば、銀行間送金と同様の業務を実行したい、口座 A から口座 B に 30 元を送金したい、Saga によると、トランザクションの原則では、グローバルトランザクション全体を次のサービスに分割します:
#転送サービス。アカウント A- ## から 30 元を差し引く操作が実行されます。 #送金補償 (TransOutCompensate) サービス、上記の送金操作をロールバックします。つまり、A のアカウントは 30 元増加します
- 送金 (TransIn) サービス、ここでは B のアカウントは 30 元増加します
- 送金 補償 (TransInCompensate) サービスを実行し、上記の送金操作をロールバックします。つまり、B アカウントが 30 元減額されます。
- トランザクション全体のロジックは次のとおりです。
送金実行成功 => 送金実行成功 => グローバルトランザクション完了
アカウント B への送金時にエラーが発生した場合など、途中でエラーが発生した場合、実行されたアカウントの補填操作が実行されます。
転送アウトの実行成功 => 転送インの実行に失敗しました=> 転送イン補償の実行に成功しました=> 転送アウト補償の実行に成功しました=> グローバル トランザクションロールバックが完了しました
次は、正常に完了した SAGA トランザクションの一般的なタイミング図です。
代码示例
以下展示在 Hyperf 框架中的使用方法,其它框架类似
namespace App\Controller;
use DtmClient\Saga;
use DtmClient\TransContext;
use Hyperf\Di\Annotation\Inject;
use Hyperf\HttpServer\Annotation\Controller;
use Hyperf\HttpServer\Annotation\GetMapping;
#[Controller(prefix: '/saga')]
class SagaController
{
protected string $serviceUri = 'http://127.0.0.1:9501';
#[Inject]
protected Saga $saga;
#[GetMapping(path: 'successCase')]
public function successCase(): string
{
$payload = ['amount' => 50];
// 初始化 Saga 事务
$this->saga->init();
// 增加转出子事务
$this->saga->add(
$this->serviceUri . '/saga/transOut',
$this->serviceUri . '/saga/transOutCompensate',
$payload
);
// 增加转入子事务
$this->saga->add(
$this->serviceUri . '/saga/transIn',
$this->serviceUri . '/saga/transInCompensate',
$payload
);
// 提交 Saga 事务
$this->saga->submit();
// 通过 TransContext::getGid() 获得 全局事务ID 并返回
return TransContext::getGid();
}
}