微服务分布式事务--破局

2020-03-04  本文已影响0人  滨岩

微服务架构下分布式事务设计实战

商品 订单 支付

分布式事务->长事务
本地事务->短事务

分布式事务: 比如 下订单->减库存->支付,订单、库存、支付都有自己DB。所以拆分为三个短事务:
1、订单事务 2、库存事务 3、支付事务,然后对这三个短事务进行协调

这时候分几种情况

1、都支付成功了,事务成功
2、假如支付失败了,幂等,而且重试了3次了,这时候需要会滚,需要把库存加上、把订单状态改成失败。

分布式事务破局
异步场景
商品交易:下单、支付


image.png

假如下单已经写到数据库DB中去了伪代码如下:

try{
  
  transation.begin();
  order.insertOrder(info);
  mqClient.sendMsg(msg);
  transaction.coomit();
 
}catch(Excetion e){
transaction.rollback()
}

如果支付失败,则需要会滚,发一条删除订单消息到MQ,然后订单消费消息,删除订单。当然这也会有问题,如果删除订单失败则又循环会滚。。。

目前比较好的方案是人工处理,支付失败会写错误日志、报警系统报警、人工删除订单。这不是AP方案,这是CP的方案,解决最终一致性的问题。

分布式事务破局2
本地事务消息表
本地操作和发送消息通过本地事务强一致性
本地事务操作表
本地事务消息表
mqMessages(msgid,content,topic,status)

对于重复消息:

比如你拿个数据要写库,你先根据主键查一下,如果这数据都有了,你就别插入了,update 一下好吧。
比如你是写 Redis,那没问题了,反正每次都是 set,天然幂等性。
比如你不是上面两个场景,那做的稍微复杂一点,你需要让生产者发送每条数据的时候,里面加一个全局唯一的 id,类似订单 id 之类的东西,然后你这里消费到了之后,先根据这个 id 去比如 Redis 里查一下,之前消费过吗?如果没有消费过,你就处理,然后这个 id 写 Redis。如果消费过了,那你就别处理了,保证别重复处理相同的消息即可。
比如基于数据库的唯一键来保证重复数据不会重复插入多条。因为有唯一键约束了,重复数据插入只会报错,不会导致数据库中出现脏数据。

上一篇 下一篇

猜你喜欢

热点阅读