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

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

单机单数据源事务

首先从单机事务开始。java

大概逻辑以下 :git

try {  
  // 开始事务
  $db->beginTransaction();
  
  // 执行你的操做 
  // ...
  
  // 提交事务
  $db->commit();
 
} catch (Exception $e) {

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

复制代码

单机多个数据源事务

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

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个请求是调用的同一个实例化后的对象。StockOrder同样。

User 调用逻辑以下:

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

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

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


复制代码

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

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

one框架完美支持上面的要求。只须要把上面的UserStockOrder添加为rpc服务便可。还须要注意beginTransactiondoTransaction方法必须返回$this提供给后面的方法调用。

user服务以下:

RpcServer::add(User::class);

复制代码

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

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

相关文章
相关标签/搜索