ICode9

精准搜索请尝试: 精确搜索
首页 > 编程语言> 文章详细

PHP 微服务之【分布式事务】

2021-01-11 17:33:49  阅读:198  来源: 互联网

标签:事务 调用 rollBack beginTransaction user commit PHP 分布式


分布式事务一直是微服务的一个难点。相关的解决方案和框架大部分是 java 的,那么 php 该如何解决呢?下面一步一步讲解如何用 php 解决分布式事务。

 

单机单数据源事务

首先从单机事务开始。

大概逻辑如下 :

try {  
  // 开始事务
  $db->beginTransaction();

  // 执行你的操作 
  // ...

  // 提交事务
  $db->commit();

} catch (Exception $e) {

  // 执行失败 回滚
  $db->rollBack();

}

 

单机多个数据源事务

如果你业务涉及到多个数据库,事务大概逻辑是这个样子:

try {  
  // 开始事务
  $db1->beginTransaction();
  $db2->beginTransaction();

  // 执行你的操作 
  // ...

  // 提交事务
  $db1->commit();
  $db2->commit();

} catch (Exception $e) {

  // 执行失败 回滚
  $db1->rollBack();
  $db2->rollBack();

}

 

多机多数据源事务(分布式事务)

如果你的数据源和业务代码都是分开的(微服务)这就是我们今天的核心。
由前面两种情况来看,大概逻辑是差不多的,主要也分为 4 个步骤。

  1. 开始事务
  2. 执行逻辑代码
  3. 提交事务
  4. 回滚事务

有些文章也称为 tcc 也就是 234 步骤。

我们用一个常用的例子:下单。
主要 3 个步骤:

  1. 创建订单
  2. 修改库存
  3. 修改用户积分

假设订单,库存,用户都是独立的服务。

按照前面的经验大概分为 4 个步骤,我们以用户为例 代码如下:

class User
{
    // 开始事务
    public function beginTransaction()
    {
        $db->beginTransaction();
        return $this;
    }

    // 执行代码
    public function doTransaction()
    {
        // 执行你的操作 
        // ...
        return $this;
    }

    public function commit()
    {
        $db->commit();
    }

    public funtion rollBack()
    {
        $db->rollBack();
    }

}

库存 (stock),订单 (order) 和上面类似,也需要这 4 个方法,我就不写了。
难点在于我们没法直接操作数据源,只能通过 rpc 调用相应的服务来操作。依次执行上面的方法就好了。代码如下:

try {  
  // 开始事务
  $user = new User();
  $stock = new Stock();
  $order = new Order();

  $user = $user->beginTransaction();
  $stock = $stock->beginTransaction();
  $order = $order->beginTransaction();

  // 执行你的操作 
  $user = $user->doTransaction();
  $stock = $stock->doTransaction();
  $order = $order->doTransaction();

  // 提交事务
  $user->commit();
  $stock->commit();
  $order->commit();

} catch (Exception $e) {

  // 执行失败 回滚
  $user->rollBack();
  $stock->rollBack();
  $order->rollBack();

}

到这里可能有人看出问题来了,正常情况下这样肯定是不行的。要上面这段代码成立需要满足 1 个条件:User 分别调用了 3 次,也就是 3 个请求。要保证这 3 个请求是调用的同一个实例化后的对象。Stock 和 Order 一样。

User 调用逻辑如下:

// 第一次请求调用
$user = new User();
$user = $user->beginTransaction();

// 第二次请求调用 复用的第一次 $user
$user = $user->doTransaction();

// 第三次请求调用 复用的第一次 $user
$user->commit();
//或者 
$user->rollBack();

注意: 虽然调用了 3 次但是只 new 了一次, 第二次和第三次请求是复用的第一次的对象。要满足这个条件 服务供方必须 常驻内存 ,而且提供的 rpc服务必须支持链式调用的功能。

one 框架 https://github.com/lizhichao/one
极简。高性能。松耦合。分布式。可运行于多种环境

one 框架完美支持上面的要求。只需要把上面的 UserStock 和 Order 添加为 rpc 服务即可。还需要注意 beginTransaction 和 doTransaction 方法必须返回 $this 提供给后面的方法调用。

user 服务如下:

RpcServer::add(User::class);

其他两个类似。到此分布式事务问题就搞定了,可能觉得这么简单吗?这主要由于 one框架的 rpc 服务提供了链式调用(多个请求复用同一个对象)的功能。

可能有人要问:如果因为网络问题或者其他问题导致最后一个服务的最后一次调用失败了怎么办?
解决方案就是事务补偿,你可以把这类极端的情况下的错误,放到一个队列里 起一服务来专门处理这里问题。

标签:事务,调用,rollBack,beginTransaction,user,commit,PHP,分布式
来源: https://www.cnblogs.com/liliuguang/p/14263246.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有