欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

最终一致性之TCC方案的执行流程 博客分类: architecture 最终一致性TCC

程序员文章站 2024-02-13 10:20:22
...

TCC是最终一致性的一个常见方案, 也是最简单的一个. 其他的方案如本地事件表, 本质上都是TCC的变种, 只是把confirm和cancel的时间往后移了而已.

 

事件表是更优雅的方案, 如果用消息队列来实现, 事件驱动架构的话, 想想都很美, 但是对于公司的遗留系统而言重构幅度较大; 相对而言TCC的引入不会遇到那么多大的阻力. 事件表方案如果出了问题, 比如消息队列崩了, 则系统就彻底歇菜. 而TCC即便没有效果, 也不会让事情变得更糟.

 

TCC的好处是实时性高, 不足之处是如果日志记录得不好, 则可能出现永远也无法恢复的数据一致性问题. 所以TCC方案一定要重视日志的作用.

 

说一个简单的TCC案例. 想象我们去电商网站购物, 点击结算的时候, 会生成一个订单, 并清空购物车, 这里就可能有出现一致性问题. 

 


最终一致性之TCC方案的执行流程
            
    
    博客分类: architecture 最终一致性TCC
 

在上图中, shoppingcart和order显然是两个不同的数据库. 所以不能直接操作order数据库, 只能通过调用OrderService来实现订单的创建, 查询和取消.  OrderService在分布式环境是不可靠的, 所以可能出现:

1. 创建订单成功, 但购物车清空可能失败. 

     和通常大学教材上说的不同, 现实世界中没有几个公司是真正地把购物车完全放到session中的; 而是要将购物车的数据持久化的, 通常是关系数据库或者键值对数据库.

     所以清空购物车其实也是数据库操作, 有可能失败, 此时订单已经创建成功, 购物车却还没有清空, 用户将会感到不安, 会纳闷刚才下的订单是不是没有真正成功.

 2. 创建订单失败, 但购物车却被清空了.

     清空购物车里的结算项目被清空, 导致用户还要重新添加一次购物车. 这时用户可能就要投诉了.

 

如果用Spring框架来实现上述流程, 则TCC的相关代码只需要负责try-confirm-cancel, 不要显式地提交或者回滚事务. 如果要回滚, TCC代码直接抛出异常就行了, 事务管理器捕获到异常后会自动回滚. 所以TCC的实现代码不要试图直接操纵事务.

 

在上图中, empty shoppingcart或者confirm时, 出错, 直接抛出异常就好了, 当前线程的事务管理器会完成本地事务的回滚.

 

cancel的时候, 无论成败都要记录日志. 如果日志是记录到数据库里, 则必须在一个新的事务里往数据库写日志.

由于Spring JpaTransactionManger不支持REQUIRE_NEW类型的事务, 则需要在一个新的线程里写日志, 此时最好用消息队列比如Kaffka, RabbitMQ来支持日志的写入. 

  • 最终一致性之TCC方案的执行流程
            
    
    博客分类: architecture 最终一致性TCC
  • 大小: 91 KB
相关标签: 最终一致性 TCC