好消息!dtm 分布式事务管理器 php 协程客户端 v0.1 beta 版本发布!!!
→ github.com/dtm-php/dtm-client
介绍dtm/dtm-client 是分布式事务管理器 dtm 的 php 客户端,已支持 tcc模式、saga、二阶段消息模式的分布式事务模式,并分别实现了与 dtm server 以 http 协议或 grpc 协议通讯,该客户端可安全运行于 php-fpm 和 swoole 协程环境中,更是对 hyperf 做了更加易用的功能支持。【推荐:php视频教程】
关于 dtmdtm 是一款基于 go 语言实现的开源分布式事务管理器,提供跨语言,跨存储引擎组合事务的强大功能。dtm 优雅的解决了幂等、空补偿、悬挂等分布式事务难题,也提供了简单易用、高性能、易水平扩展的分布式事务解决方案。
亮点极易上手零配置启动服务,提供非常简单的 http 接口,极大降低上手分布式事务的难度跨语言可适合多语言栈的公司使用。方便 go、python、php、nodejs、ruby、c# 等各类语言使用。使用简单开发者不再担心悬挂、空补偿、幂等各类问题,首创子事务屏障技术代为处理易部署、易扩展仅依赖 mysql/redis,部署简单,易集群化,易水平扩展多种分布式事务协议支持tcc、saga、xa、二阶段消息,一站式解决多种分布式事务问题对比在非 java 语言下,暂未看到除 dtm 之外的成熟的分布式事务管理器,因此这里将 dtm 和 java 中最成熟的开源项目 seata 做对比:
特性dtmseata备注
支持语言 go、c#、java、python、php… java dtm 可轻松接入一门新语言
存储引擎 支持数据库、redis、mongo等 数据库
异常处理 子事务屏障自动处理 手动处理 dtm 解决了幂等、悬挂、空补偿
saga事务 极简易用 复杂状态机
二阶段消息 ✓ ✗ 最简消息最终一致性架构
tcc事务 ✓ ✓
xa事务 ✓ ✓
at事务 建议使用xa ✓ at 与 xa类似,但有脏回滚
单服务多数据源 ✓ ✗
通信协议 http、grpc dubbo等协议 dtm对云原生更加友好
star数量 dtm 从 2021-06-04 发布 0.1版本,发展飞快
从上面对比的特性来看,dtm 在许多方面都具备很大的优势。如果考虑多语言支持、多存储引擎支持,那么 dtm 毫无疑问是您的首选.
安装通过 composer 可以非常方便的安装 dtm-client
composer require dtm/dtm-client
使用时别忘了启动 dtm server 哦配置配置文件如果您是在 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 中间件作为 server 的全局中间件,该中间件支持 psr-15 规范,可适用于各个支持该规范的的框架。
在 hyperf 中的中间件配置可参考 hyperf文档 - 中间件 一章。
使用dtm-client 的使用非常简单,我们提供了一个示例项目 dtm-php/dtm-sample 来帮助大家更好的理解和调试。
在使用该组件之前,也强烈建议您先阅读 dtm 官方文档,以做更详细的了解。
tcc 模式tcc 模式是一种非常流行的柔性事务解决方案,由 try-confirm-cancel 三个单词的首字母缩写分别组成 tcc 的概念,最早是由 pat helland 于 2007 年发表的一篇名为《life beyond distributed transactions:an apostate’s opinion》的论文中提出。
tcc 的 3 个阶段try 阶段:尝试执行,完成所有业务检查(一致性), 预留必须业务资源(准隔离性)
confirm 阶段:如果所有分支的 try 都成功了,则走到 confirm 阶段。confirm 真正执行业务,不作任何业务检查,只使用 try 阶段预留的业务资源
cancel 阶段:如果所有分支的 try 有一个失败了,则走到 cancel 阶段。cancel 释放 try 阶段预留的业务资源。
如果我们要进行一个类似于银行跨行转账的业务,转出(transout)和转入(transin)分别在不同的微服务里,一个成功完成的 tcc 事务典型的时序图如下:
代码示例以下展示在 hyperf 框架中的使用方法,其它框架类似
<?phpnamespace 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 模式是分布式事务领域最有名气的解决方案之一,也非常流行于各大系统中,最初出现在 1987 年 由 hector garcaa-molrna & kenneth salem 发表的论文 sagas 里。
saga 是一种最终一致性事务,也是一种柔性事务,又被叫做 长时间运行的事务(long-running-transaction),saga 是由一系列的本地事务构成。每一个本地事务在更新完数据库之后,会发布一条消息或者一个事件来触发 saga 全局事务中的下一个本地事务的执行。如果一个本地事务因为某些业务规则无法满足而失败,saga 会执行在这个失败的事务之前成功提交的所有事务的补偿操作。所以 saga 模式在对比 tcc 模式时,因缺少了资源预留的步骤,往往在实现回滚逻辑时会变得更麻烦。
saga 子事务拆分比如我们要进行一个类似于银行跨行转账的业务,将 a 账户中的 30 元转到 b 账户,根据 saga 事务的原理,我们将整个全局事务,拆分为以下服务:
转出(transout)服务,这里将会进行操作 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(); }}
以上就是【dtm】php协程客户端v0.1 beta版本发布啦!的详细内容。