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

过去十几年的分布式计算

从十多年前ejb盛行的年代,到后来的soa时代,一直到今天的微服务时代,虽然技术在不断飞速的进化,但是分布式计算这只“怪兽”却一直没有被打败,反倒是随着互联网浪潮 更加肆意的兴风作浪 为害人间。

分布式意味着数据一致性难以保障 性能开销大 开发和测试成本高 运维难度大。。。

多少程序员架构师多少个黑白颠倒的加班人月 多少深夜的版本上线 多少运维人员的血汗,都是拜分布式系统所赐。

第一道判断题——你是否需要分布式

分布式架构第一原则——不要分布你的组件。——马丁福勒

其实还应该补充一局——架构设计第一原则——尽量不要把系统设计成分布式。

所以 ,每一个负责的架构师都首先要做一个理性的判断,切不可为了赶时髦而跳进分布式的坑,这坑里已经尸骨如山。

在我看来,选择分布式的合适理由包括:

  • 1接手了分布式的遗留系统,
  • 2已存在的多个独立系统,替换成本高昂,只能集成。跟情况1很类似。
  • 3需要对接外部系统,此时就算你的系统本身是单体的,但是跟外部系统一起构成了分布式。
  • 4巨型系统,巨型团队,各部分应用场景和要求差异巨大,单一的系统不能满足业务,并且发布周期过长和巨型团队难以展开和协调。

不难看出,前三个情况没什么可讨论的,只能接受,不过好在这样的场景 往往对系统的集成度 对分布式计算的实时性一致性要求也不高。

重点是第四种情况,这是决定性的判断和选择,需要慎重的考虑。

cap难题与base方案

进入互联网电商时代以后,分布式往往和高并发一通出现,因此我们实际上是面对两只怪兽了。在这种共同夹击下,出现了cap难题—— 一致性 可用性 和可分布性 三者难以同事实现,尤其是用传统的acid事务。

业务长事务最终一致性难题

ACID事务非常有价值,但是它的局限性也是很明显的——只适用于短事务,对”业务长事务”无能为力。

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

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

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

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

Sagas事务模型的实现机制:

  • 每个业务活动都是一个原子操作;
  • 每个业务活动均提供正反操作;
  • 任何一个业务活动发生错误,按照执行的反顺序,实时执行反操作,进行事务回滚;
  • 回滚失败情况下,需要记录待冲正事务日志,通过重试策略进行重试;
  • 冲正重试依然失败的场景,提供定时冲正服务器,对回滚失败的业务进行定时冲正;
  • 定时冲正依然失败的业务,等待人工干预;

Sagas长事务模型支持对数据一致性要求比较高的场景比较适用,由于采用了补偿的机制,每个原子操作都是先执行任务,避免了长时间的资源锁定,能做到实时释放资源,性能相对有保障。
Sagas长事务方式如果由业务去实现,复杂度与难度并存,因此需要开发一套支持Sagas事务模型的框架来支撑业务快速交付。

转自 https://blog.csdn.net/qq_14828239/article/details/80523815

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可以有效的给热点降温,原理就是“用空间和时间稀释复杂性”。其实这并不是创新方法,很多有经验的设计者就在有意无意的这样做 典型的如各种跑批处理,只不过没有明确这个概念而已。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值