阿里称已有一种解决世界性难题的方案,无论是效率还是可靠性都超过目前的分布式事务技术
可惜是收费的,还必须依赖阿里云的分布式数据库
分布式事务就是一个大操作分成很多小操作,在不同服务器上,最后要么一起成功,或一起失败,必须是一个整体性的事务
比如淘宝买吃的,要减库存然后扣钱,库存和扣钱是两个服务,如果扣钱失败了,那么库存要还原,反之一样
不把分布式事务处理好,后果很严重
TCC分布式事务
TCC的意思很简单,T(Try)C(Confirm)C(Cancel)
TCC之Try
以上面打的比方为例,买吃的下单逻辑大概是这样:
订单一般都有状态,那么应该改一下代码
// 修改订单状态为更新中
orderService.updateStatus("OrderStatus.UPDATEING");
意思就是别着急把状态改为“已支付”,先给个预备状态“修改中”
然后减库存也是,可以先冻结库存(先修改库存为98也可以),比如100-2=98,然后把2存到一张冻结表里,表示有2个库存被冻结
同理,扣钱也是,比如支付100,放冻结表里,表示有100块要扣除
以上就是TCC的Try阶段:不是直接完成业务操作逻辑,而是完成一个Try操作
这个操作会锁住一些资源
TCC之Confirm
上面操作完成之后,会有2个结果,成功或失败
如何知道结果?需要引入TCC框架:
框架名称 | Github地址 | star数量 |
---|---|---|
tcc-transaction | https://github.com/changmingxie/tcc-transaction | 2446 |
Hmily | https://github.com/yu199195/hmily | 1381 |
ByteTCC | https://github.com/liuyangming/ByteTCC | 1300 |
EasyTransaction | https://github.com/liuyangming/ByteTCC | 904 |
那么就需要手动改之前的状态了
// 修改订单状态为:已支付
orderService.updateStatus("OrderStatus.PAYED");
其他库存/扣钱服务都需要修改,将冻结的库存和钱修改为0,完成一个正常的扣减
框架会自动执行各个服务的逻辑
TCC之Cancel
如果扣钱服务异常,TCC框架也会感知到,会对整个TCC事务进行回滚,即执行Cancel阶段
跟上面一样,也需要修改状态
// 修改订单状态为:已取消
orderService.updateStatus("OrderStatus.CANCELED");
既然扣钱失败,库存那边肯定已经减了,就需要将库存还原
把冻结的库存和钱减去,加到原库存和钱里去
ps:上面例子的状态,不是必须有的,看业务是否需要
TCC总结
1.要用TCC事务需引入TCC事务框架
2.原本1个接口,要改为3个逻辑(Try-Confirm-Cancel)
3.Cancel和Confirm逻辑必须要幂等
如果在CC阶段,服务突然挂掉了,会反复调用,直到成功(一致性) tips:可以设置最大重试次数,实在不行人工操作
如果中间件/数据库挂了,会执行Cancel,Try回滚
优点
1.降低锁冲突
2.将数据库的2PC提到应用层来实现,数据库是1PC,提高吞吐量
缺点
1.代码量增多,开发成本高
2.业务侵入
摘自:
石杉的架构笔记