最近做了一个面向微服务的交易最终一致性框架

30 views
Skip to first unread message

liyingquan

unread,
Jul 18, 2019, 12:53:12 AM7/18/19
to agilechina
各位感兴趣的帮忙看看,
我自己觉得“易最终一致性”这个轮子还是有必要造一个的,市面上还没看到成熟和广泛采纳的。

ETF:Elastic Transaction Framework
弹性事务概述
ACID事务虽好,但局限性也是很明显的——仅适于单系统本地事务处理,在微服务和互联网开放架构时代已经远远无法满足要求。

你不可能要求外部第三方的系统跟你绑定在同一个ACID事务上下文,更何况很多时候你集成的服务或API本身就是非事务性的,HTTP也不支持事务上下文传播;

你也很难要求组织内的另一个团队的系统跟你的系统纳入同一个ACID事务上下文,为了灵活性、扩展性、性能等很多架构考量都不能那么做。

就像物理世界静止是相对的运动是绝对的,软件世界的现实是:单系统ACID的简单幸福是相对的、一时的,分布式的复杂和痛苦才是永恒的真相!

IT大厂是最早感受分布式+高并发痛苦的,即著名的CAP难题,它们也早就指出了解决之道——一种折中的方案——最终一致性, 理论的就不展开介绍,可以搜索关键字CAP、BASE、TCC、幂等。

归纳起来结论就是:

ACID刚性事务存在很多局限性,不适合互联网时代的分布式计算,
必须设计一种柔性/弹性的事务机制,所谓弹性就是不追求实时严格的事务一致性,只需保证最终一致性;
ETF弹性事务框架介绍
本项目的目标是为那些无法享受acid事务的java分布式系统和微服务的开发,提供一种简单有效的交易最终一致性解决方案。

虽然优秀的程序员不用任何ETF之类的框架也能够手打出一个可靠的复杂交易系统,但是框架可以显著提高工作效率、架构质量和稳定性;

ETF是一个JAVA弹性事务开发框架,可以帮助程序员更加优雅、简单的处理交易的幂等、防重复、失败重试、成功后的交易结果查询、失败回退、交易日志。。。

以上这些其实都是非功能性需求,如果没有框架的帮助,这些非功能性的关注点很可能会跟真正的业务逻辑掺杂在一起, 这是很多系统维护成本高企、质量糟糕的根源。

ETF相对于其它同类项目的特点/优势:

针对可撤销和不可撤销的交易,提供两种处理模式:1、TCC模式处理可撤销的交易;2、失败重试模式处理不撤销复交易;后面详细解释;
使用方式比较简单优雅,框架侵入性低;annotation声明式的使用风格,对API参数返回值无限制,见后面的代码示例;
基于Redis数据库记录问题交易日志、协调ETF事务上下文,性能好,学习成本低;
提供Template模板辅助类,可以显著改善代码风格和质量;熟悉Spring的程序员会非常喜欢这种编程模型;
详细记录问题交易的执行过程,便于排查问题、恢复故障;
提供交易管理控制台UI,方便监控;
套用一句很多framework常用的宣传语——ETF可以让开发人员把更多精力用在真正的业务逻辑开发上。

ETF两种交易类型
虽然总是在说交易、交易系统,但是其实交易也分不同类型的;

我将复杂交易系统中的交易分成两类:可撤销的交易和不可撤销的交易;

判断交易是不是可撤销的依据:
凡是不在你的架构权限管辖内的系统的接口(包括组织内和外部第三方),默认都看作不可撤销的交易; 因为这样的接口一旦调用了其中的写操作,通常是没有办法通过调用另外一个操作直接撤销的;只能走另外的流程(例如退款、退货)做反向处理;
可撤销的交易需要专门的设计,这就涉及到了TCC模型;简单说就是把交易设计成分阶段执行:try阶段锁定资源,confirm阶段执行交易,cancel撤销交易;
本质区别就是:前者无法在出错时立即撤销,必须走另外流程(技术或业务功能)撤销;而后者在交易模型设计上就预留了撤销操作接口,可以出错后直接撤销,无需另外流程;
两种交易的应用场景和处理模式
不可撤销交易的应用场景比较多,基本上与外部接口打交道的都是,典型的应用就是系统对接第三方支付通道,通常采用的交易保证机制是:

支付平台回调/通知结果;通知无响应时会以阶梯时间段不断重试,直到有应答;
本系统主动轮询支付结果;
每日对账;
典型支付场景的设计策略是:即便出现延迟或错误,也要尽量让交易成功,因为恢复/回退交易的成本太高,会影响用户体验(重新支付引起用户疑虑)。

其实这种策略是很务实也很有效的,因为运行时的报错延迟主要都是技术原因,很多情况下也都是短暂的,完全可以也应该通过重试机制来促成交易最终的完成, 大多数情况下回退/撤销不是一个明智的做法。

对于可撤销交易,就可以应用TCC模式同步交易的各个环节分别做try操作,然后同步各环节做confirm或cancel; TCC可撤销交易仅适用于组织内部统一架构实施,对于外部系统则无能为力。不过TCC一旦做成了也会具有更高的系统可靠性。

归纳起来就是:

对不可撤销交易,出错时重试,延迟响应时轮询结果;
对于可撤销交易,出错时撤销;
ETF框架对以上两种交易类型都有支持,开发人员只需:

扩展框架提供的TccTemplate模板,在框架提供的扩展点/回调中填充业务逻辑;
在组件API上以annotation声明交易类型、TCC规则或重试规则; 就可以实现一个具有最终一致性的ETF交易组件。
ETF框架的低侵入性编程模型
好的开发框架应该同时具备“简单明确的契约和编程模型”和“尽量低的侵入性、对业务开发尽量少的干扰”两个特征。

ETF要求用enum枚举类定义交易类型,这虽然是一个限制,但其实也是一个最佳实践。交易类型是如此的重要,完全配得上用一个枚举类型进行明确的声明和定义。
ETF框架通过annotation配置TCC规则和重试/查询回调规则,对业务组件的入参和返回值完全不做限制;
正是由于使用了enum定义交易类型,ETF组件的配置具有了类型安全,框架在运行时也能发现配置不一致问题,尽早暴露很多隐藏的错误;这就是简单明确的编程模型的体现,让使用者不容易犯错。
业务开发人员只需把业务逻辑按照Etf模板类的规范分解填充到各个回调接口中,即可获得TCC和交易重试和交易查询回调。
贴一段代码展示ETF如何低侵入性的对业务代码做弹性事务增强,

不难看出,这是一个“不可恢复交易”型组件,ETF为其提供了retry和query机制确保交易(在暂时出错的情况下也能尽量)执行成功。

Mike Zhang

unread,
Jan 2, 2020, 5:48:29 PM1/2/20
to agile...@googlegroups.com
今天在微信群里面聊到了本群。
——————————————————
10年前TW维护在Gmail的敏捷邮件列表比现在的微信群tough多了- 提小白问题被批,提疑难问题也被批,分享被批,开展调查被批。
后来几乎没有人敢再发言。
在Gmail被大陆封锁之前,那邮件列表成功地自我封锁。
——————————————————

Eugene Cao

unread,
Jan 31, 2020, 1:50:04 AM1/31/20
to agile...@googlegroups.com
没有啥人用了,大咖门都维护自己的 微信群,星球,简书。 既能分享又能挣钱。 

这里就是一个过往的历时。  还有一些大咖都去 帝国了

--
--
敏捷中国 http://www.agilechina.net 邮件列表
如果想发起讨论,请发送邮件到 agile...@googlegroups.com
如欲退订请发送邮件到 agilechina-...@googlegroups.com
更多选项,请访问 http://groups.google.com/group/agilechina
---
您收到此邮件是因为您订阅了Google网上论坛上的“敏捷中国”群组。
要退订此群组并停止接收此群组的电子邮件,请发送电子邮件到agilechina+...@googlegroups.com
要在网络上查看此讨论,请访问https://groups.google.com/d/msgid/agilechina/CACCrcBFTumEq6fdVo7YZh6T9LTWpfu0ypJBNc3Y4pUnQ2Bku8w%40mail.gmail.com

Jeff Xiong

unread,
Jan 31, 2020, 7:55:13 AM1/31/20
to agile...@googlegroups.com

首先是没多少人用邮件列表了吧。

 

-- 

Jeff Xiong

Xulin Zhuang

unread,
Jan 31, 2020, 8:07:20 AM1/31/20
to agile...@googlegroups.com
现在基本上很少人用邮件列表了,几乎看不到任何信息,大家可能比较习惯使用其他工具了。

Jeff Xiong <gigi...@gmail.com> 于2020年1月31日周五 下午8:55写道:

Jeff Xiong

unread,
Jan 31, 2020, 8:26:43 AM1/31/20
to agile...@googlegroups.com

要我说的话,我倒是更喜欢用邮件列表。十几年前聊的东西,现在照样可以搜索到。微信你搜索十几天前聊的内容试试。

 

-- 

Jeff Xiong

Reply all
Reply to author
Forward
0 new messages