分布式事务的华丽进化 | 京东物流技术团队
说到分布式事务,大家并不陌生。在实际工作中,用得比较多的还是柔性分布式事务,今天主要把在工作中运用到的几种柔性分布式事务的场景及实现方式做一个简单介绍,也可以看做是柔性分布式事务的一个演进过程。
一、调用方保证
这种方式适合业务内自己使用,当方法内的任务一个逻辑发生异常时,整个方法都异常,由调用方进行重试。该方法不太适合于外部系统的交互,否则,这就是把自己的命运交到别人的手里,是比较危险的做法。
在上述调用示意图中,内部应用 APP1 和 APP2 之间,APP1 的方法 method1 调用 APP2 里的 method2 方法,method2 里有分布式事务逻辑,当分布式事务中的逻辑异常后,method2 方法都失败或抛出异常,method1 收到返回值是失败或异常后,都需要重试调用 method2,确保 method2 执行成功。method2 本身则需要确保逻辑中已经成功的逻辑再次被调用时处理也要正确。
该方法不建议大家在工作中使用,仅从保证分布式事务的正确性看是可以使用的,但从 Java 的规范上看,这种方法属于用异常控制流程,并不是很规范。同时,如果分布式事务中的逻辑是写本地库,发消息或 RPC 远程调用,则一般不建议把事务和发消息或 RPC 调用放到事务方法内,避免大事务。
二、定时任务扫描业务表
该场景主要运用于流量小、业务场景较单一的场景,或是业务处于验证阶段,为了快速验证业务是否有价值阶段,直接用业务表来做任务表,避免建多张表。在用本地事务写完业务表后,事务正常提交即可。通过一个定时任务查询业务表的增量数据,在定时任务中处理其他业务逻辑。
该方案一般作为过渡方案,最终业务量上来后,会升级到下面的本地任务表的方案。
三、本地任务表
这是比较典型的分布式事务的解决方案,即:在业务库中,同步建一个任务表。业务表和任务表在本地事务中同时写入,再由一个定时任务定时查询任务表,把任务读取到后根据业务逻辑要求进行处理。
业务表和任务表在一个数据库中,由数据库的一个事务控制器实现事务。在应用中,另起一个定时任务,由定时任务去查询任务表,把任务表中新进的任务抓取后执行该定时任务需要执行的业务逻辑。
该方案实际运用时,定时任务的稳定性需要我们特别关注,定时任务的稳定性决定我们该方案的可用性。建议把定时任务的执行情况监控起来,确保有问题时能第一时间处理,避免影响业务。
四、组件抽取
目前,对于 Java 语言开发的团队,其框架大部分都以 Spring 为主,故可基于 SpringEvent 异步事件做一个小的组件封装。主要思路为在事务中,发送 Event 异步事件,当异步事件发送成功则事务提交结束,当异步事件发送失败则异步任务落本地数据库后事务再提交结束,然后通过定时任务从任务表中抓取任务执行。
该方案以 SpringEvent 异步事件为主做了一个组件,当 SpringEvent 异步事件发送异常后,降级到本地任务表,确保异步任务的可靠性。即使没有封装为组件,在实际工作中,还是比较推荐大家使用该方案。
当然,如果项目中没有使用 Spring 框架也没问题,有了上述的思想,可以根据自身使用的框架情况进行调整。正所谓“只要思想不滑坡,办法总比困难多”。
作者:京东物流 廖宗雄
来源:京东云开发者社区 自猿其说 Tech 转载请注明出处
版权声明: 本文为 InfoQ 作者【京东科技开发者】的原创文章。
原文链接:【http://xie.infoq.cn/article/436562fd1557c08b1afc42b7e】。文章转载请联系作者。
评论