TCC模式的补偿模式中如何确保写隔离?

《分布式事务之Seata》这本书中提到过:常见的TCC实现模式有两种,分别是“资源预留模式”与“补偿模式”。
TCC资源预留模式的典型就是A向B转账场景使用“冻结金额”的这种模式:

prepare:
    A.balance不变        A.freeze+amount
    B.balance不变        B.freeze+amount
commit:
    A.balance-amount    A.freeze-amount
    B.balance+amount    B.freeze-amount
rollback:
    A.balance不变        A.freeze-amount
    B.balance不变        B.freeze-amount

TCC补偿模式的例子这里借用书中的“下订单+减库存”场景:

phase 1:
    order.insert()    stock.deduct() & stock.record()//记录库存变化流水
phase 2.commit:
    order.什么也不做    stock.deleteRecord()//删除库存变化流水
phase 2.rollback:
    order.delete()    stock.add()//补偿phase1减少的库存 & stock.deleteRecord()

AT模式因为有全局锁的存在,所以可以较容易的处理读写隔离问题。
而TCC的”资源预留模式“的读写隔离也比较容易理解,相当于把“变化”放到预留的资源上去执行,而平时关注的balance在全局事务为提交/回滚前是不变的,所以也实现了读写隔离(不考虑@Transactional这种本地事务)。
但TCC的“补偿模式”是如何做到读写隔离的呢?以书上给的这个“下订单+减库存”的例子来说:tx1刚刚完成phase1但还没有进入到phase2,此时tx2也是一个全局事务,且做的动作是更新order,那不就无法做到写隔离了吗?

阅读 2.7k
2 个回答

问题本身就不成立,因为压根就不隔离、哪有什么怎么保证。

这也是补偿模式中的一个明显缺陷。

一般解决思路是业务上自己想办法处理(比如引入单独的锁机制),框架和协议本身不做处理,当然这也带来了侵入性较大等一些其他问题。

TCC模式没有严格要求要做到写隔离,要根据实际的业务场景做调整,一般情况下强制需要保证的只有3个接口的幂等性。
如果出现问题中的场景:两个不同业务下的全局事务都在try阶段对同一个行记录做更新,那么可以考虑在二阶段对更新的记录做类似cas的检查,如果成功则正常提交,如果检查失败则根据具体的场景做判断,或者做记录并转人工处理。

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进