基于Hyperf框架的TCC分布式事务组件

Overview

hyperf-tcc

基于 Hyperf 框架的分布式事务 TCC 组件

  • 因为有些 Composer 组件依赖的版本可能过高无法低版本兼容, 欢迎PR帮忙解决
  • 已经经过 AB -N 1000 -N 100 压测测试, 无失败事务, 全可回滚, 数据无异常
  • 实现思路参考 loyaltylu/tcc-transaction 该作者写的
  • 为啥要重写, 因为他使用了太多 AOP 并且代码 可读性较差 用的不太顺就自己搞了一个
  • 欢迎 测试PR

Install

在使用 tcc 前先确保已经安装 Redis, Nsq

composer require h6play/hyperf-tcc

发布资源

php bin/hyperf.php vendor:publish h6play/hyperf-tcc

执行迁移

php bin/hyperf.php migrate

Run

use H6Play\TccTransaction\Example\Test;

   /**
    * @GetMapping(path="nsq")
    */
    public function nsq(RequestInterface $req, ResponseInterface $res)
    {
        $goodsId = $req->input('goods_id', 1);
        $couponId = $req->input('coupon_id', 0);
        $result = (new Test())->handle($goodsId,$couponId);
        return $res->json([
           'code' => 0,
           'data' => $result,
        ]);
    }

Test

Benchmark

curl http://localhost:9501/index/nsq?goods_id=1&coupon_id=0

{"code":0,"data":{"order":{"order_sn":255041892524236800,"body":"购买桃子","total_fee":"200.00","goods_id":1,"id":2483},"goods":{"id":1,"price":"200.00","name":"桃子","num":9994,"lock":0,"sale":6},"coupon":null}}

注意事项

  • 分布式事务, 本身是为了确保数据一致性, 在高并发测试下, 应该对接口服务做好限流(使用RateLimit组件)

Nsq配置教程

参考文档

1. nsqlookupd
2. nsqd --lookupd-tcp-address=127.0.0.1:4160

config/autoload/nsq.php 使用默认配置端口即可

功能列表

  • 实现TCC操作实现接口 TccOption
  • 实现事务处理 Tcc
  • 实现事务编排 Tcc->rely(...)
  • 实现事务重试 NSQ消息订阅
  • 实现无法回滚事务记录并通知 Database

Composer依赖

  • "hyperf/nsq": "^2.1"
  • "hyperf/redis": "~2.1.0"
  • "hyperf/database": "~2.1.0"
  • "hyperf/snowflake": "^2.1"
  • "hyperf/logger": "~2.1.0"
  • "hyperf/db-connection": "~2.1.0"

使用方式

  • Tcc 事务创建
    • 对于事务进行流程编排
    • 对于事务的启动操作
  • TccOption 事务操作
    • 需要针对性实现 try, confirm, cancel 方法
    • 例如 商品库存锁定, 商品库存扣除
    • H6Play\TccTransaction\Example\Tcc 下能看到很多演示写法
    • 不应当把 复杂的参数 放到该类中去例如对象等, 因为它会作为一个 序列化的类 存放到 redis
    • 如果操作类 参数过多, 或者 属性对象过多 会造成 存储负担
    • 不推荐在 TccOption 操作类中写业务逻辑, 它应当作为一个调用服务的封装
  • TccState 事务状态
    • 存放操作和状态并且序列化到缓存中
  • Coordinator/TccCoordinator 事务协调者 NSQ消费者 需要加入到消费进程
    • 请先继承该类实现 NSQ消费者进程绑定 @Consumer 注解
    • 具体查看 Hyperf NSQ文档

代码演示

  • 下面的代码演示都在 Example 中有实现
  • Example\Tcc\* 事务操作项
  • Example\Service\* 微服务实现类
  • Example\Test 模拟下单接口
  • Example\database.sql 演示案例数据库脚本, 测试前先导入
use H6Play\TccTransaction\Tcc;
use H6Play\TccTransaction\Example\Tcc\GoodsLockTcc;
use H6Play\TccTransaction\Example\Tcc\CouponLockTcc;
use H6Play\TccTransaction\Example\Tcc\OrderTcc;
use H6Play\TccTransaction\Example\Tcc\GoodsSubTcc;
use H6Play\TccTransaction\Example\Tcc\CouponSubTcc;
use H6Play\TccTransaction\Example\Tcc\OrderMessageTcc;
use H6Play\TccTransaction\Example\Tcc\OrderStatisticsTcc;

$goodsId = 1;
$couponId = 0;
$tcc = new Tcc;
$tcc
    ->tcc(1, new GoodsLockTcc($goodsId)) // 商品库存锁定
    ->tcc(2, new CouponLockTcc($couponId)) // 优惠券锁定
    ->tcc(3, new OrderTcc) // 创建订单
    ->tcc(4, new GoodsSubTcc) // 扣减库存
    ->tcc(5, new CouponSubTcc) // 占用优惠券
    ->tcc(6, new OrderMessageTcc) // 创建订单消息
    ->tcc(7, new OrderStatisticsTcc) // 订单统计
    ->rely([          // 配置执行流程
        // 外层步骤是逐步执行的
        // [...] 内层步骤是同步执行的
        [1, 2],       // 1,2 锁定库存, 锁定优惠券
        [3],          // 3 创建订单
        [4, 5, 6, 7], // 4,5,6,7 扣减库存, 占用优惠券, 订单消息, 订单统计
    ])->begin(); // 开启事务

实现原理

  • TccOption 都必须实现 try, confirm, cancel 方法
  • 其中 confirm 允许空操作

联系方式

  • 请通过微信联系作者,并备注 PHP 方便辨认
  • 请通过扫码,或者添加微信 h6play

You might also like...
Releases(1.1.0)
Owner
null