基于 TxFlow"分步"式服务交易保证框架 构建灵活可靠的分布式系统

12 views
Skip to first unread message

Vincent Lee

unread,
Jan 4, 2019, 4:56:17 AM1/4/19
to agilechina
业务长事务最终一致性难题
ACID事务非常有价值,但是它的局限性也是很明显的——只适用于短事务,对”业务长事务”无能为力。

正如“基于SOA或微服务架构的面向过程编程”一样具有讽刺意味,我最近发现了另一个诡异的做法——“基于acid短事务一致性技术的长事务编程”,这非常的有趣,就好比“使用裁缝软尺进行地质测绘”。

其实这种事情我和很多人一样,已经干了十几年了,并不是觉得裁缝软尺没问题很好用,只是因为熟悉 于是习惯性的接受了。

引用一句我刚刚想出来的民谚——“如果一个问题没有被当做一个问题,那么它的解决方案将永远不会出现。”

但是 最近我参与的一个项目 让我意识到不能再这样干了,因为我在该项目中看到了一段让我无法忍受的代码——有人为了实现一个包含5个步骤的业务,以硬编码方式分别调用了5个方法,这不是关键,更要命的是这五5个步骤都有可能出错,而且此项目对接了银行系统涉及资金操作 因此要求对任何错误异常进行合理的处理 以确保系统始终处于一致的状态(此处所谓状态一致 就是这5个步骤要么全都正确执行 要么全都不执行),于是这个程序员继续以硬编码方式分别处理5种出错情况——对已经执行了的步骤进行撤销。

Sagas事务模型的实现机制:
每个业务活动都是一个原子操作;
每个业务活动均提供正反操作;
任何一个业务活动发生错误,按照执行的反顺序,实时执行反操作,进行事务回滚;
回滚失败情况下,需要记录待冲正事务日志,通过重试策略进行重试;
冲正重试依然失败的场景,提供定时冲正服务器,对回滚失败的业务进行定时冲正;
定时冲正依然失败的业务,等待人工干预;
Sagas长事务模型支持对数据一致性要求比较高的场景比较适用,由于采用了补偿的机制,每个原子操作都是先执行任务,避免了长时间的资源锁定,能做到实时释放资源,性能相对有保障。
Sagas长事务方式如果由业务去实现,复杂度与难度并存,因此需要开发一套支持Sagas事务模型的框架来支撑业务快速交付。


TxFlow分步式服务交易保证框架
在不断遇到业务长事务问题过程中,我发现这根工作流引擎WorkFlow要解决的问题有很多相似之处,

区别仅在于workflow问题偏重于复杂流程的多人协作交互,而业务长事务问题关键点在于事务的最终一致性、可恢复性。

于是我借鉴workflow模型设计出了这个TxFlow框架:

  • 首先把每一个业务长事务抽象成一个TxFlow组件,比如LendingTxFlow、TransferTxFlow。。。extends共同父类AbsTxFlow
  • 定义TxFlow步骤:将TxFlow的步骤Step 以枚举值集合的形式定义在具体的TxFlow中,@override TxFlowStep[] getSteps()
  • 定义TxFlow步骤的实现:在TxFlow中为每个Step定义实现方法;@TxFlowStep private TxFlowStepCallBack stepXxx(){ return new TxFlowStepCallBack (){...}; } 其中TxFlowStepCallBack 为借口 用于框架回调真正的业务逻辑;
  • 定义TxFlow实例标识:在共同父类AbsTxFlow中,定义BizSerialNo和FlowClass字段用于标识不同的Instance实例;
  • 定义TxFlow实例状态:在TxFlow属性中声明@TxFlowState状态字段 用于存储流程实例的状态;
  • 经过以上定义 便得到了一个业务长事务的定义/模板,
  • 在运行时,只需对TxFlow进行实例化、持久化、反序列化、调用Step业务逻辑、关闭TxFlow实例等生命周期操作,即可实现对业务长事务的管理;
  • TxFlow的监控与控制:开发一个控制台界面 展示TxFlow实例的列表(标识字段、状态字段、当前步骤、更新时间。。。),点击当前状态 可以查看执行细节(日志信息、报错信息等),对于出错的step 可以重试或回滚;
  • TxFlow的自动执行和恢复:开发一个或多个Quartz跑批——TxFlowJob,对运行中的流程实例进行恢复(从数据库load并对状态反序列化)并执行(调用下一step);
  • TxFlow的新建和启动:new XxxTxFlow(bizNo).start();
  • TxFlow的调用:new XxxTxFlow(bizNo).doFunction(param1,parame2...); 这种情况是bizNo对应的XxxTxFlow实例已经存在的前提下,对其进行恢复并调用特定步骤的方法;跟TxFlowJob类似,只不过不是定期自动调用 而是在系统的对外服务接口(如Dubbo的Facade)处 进行回调处理;
以上 就是TxFlow框架的概要设计,实现起来并不复杂,只要熟悉Java的反射API和Annotation的使用即可。

TxFlow相当于实现了一个简单的Sagas;

TxFlow的附加价值——数据流可视化,空间换复杂度
我们在搭建应用系统过程中经常能发现一个现象,就是系统的复杂度主要集中在少数几个模型(对应的表),逐渐的系统为了适应业务发展变化会不断的调整这些模型以及围绕这些模型的程序逻辑,于是系统维护的热点产生了。

txflow可以有效的给热点降温,原理就是“用空间和时间稀释复杂性”。其实这并不是创新方法,很多有经验的设计者就在有意无意的这样做 典型的如各种跑批处理,只不过没有明确这个概念而已。
--------------------- 
作者:Vincent2013SH 
来源:CSDN 
版权声明:本文为博主原创文章,转载请附上博文链接!
Reply all
Reply to author
Forward
0 new messages