微服务架构流行的今天,一次交易需要跨越多个“服务”、多个数据库来实现,传统的技术手段,已经无法应对和满足微服务情况下这些复杂的场景了。针对微服务下的交易业务如何保障数据一致性,本文尽量做到理论结合实际,将我们在实际产品中用到的分布式事务实现机制,和大家扒一扒,希望能帮助到读者。
谈到分布式事务,必须先把”cap"拿出来说说事......,当然还有”base"......
从架构的角度来看,业务拆分(数据分区)、数据一致性、性能(可用性)永远是个平衡的艺术:
1)在微服务架构下,为了获得更高的性能与灵活性,将业务应用拆分为多个,交易跨多个微服务编排,数据一致性的问题产生;
2)为了解决数据一致性问题,需要采用不同的事务机制来保障,这又会产生性能(可用性)问题;
在计算机世界里,为了解决一件事情,另外的问题就会接踵而至,从另一个层面印证了it架构永远是一种平衡的艺术。
“base”其核心思想是根据业务特点,采用适当的方式来使系统达到最终一致性(eventualconsistency);在互联网领域,通常需要牺牲强一致性来换取系统的高可用性,只需要保证数据的“最终一致”,只是这个最终时间需要在用户可以接受的范围内;但在金融相关的交易领域,仍然需要采用强一致性的方式来保障交易的准确性与可靠性。
分布式事务介绍
接下来为大家介绍业界常见的事务处理模式,包括两阶段提交、三阶段提交、sagas长事务、补偿模式、可靠事件模式(本地事件表、外部事件表)、可靠事件模式(非事务消息、事务消息)、tcc等。不同的事务模型支持不同的数据一致性。如果读者对这几种分布式事务比较熟悉,可以直接参考下图并结合自身业务需求选择合适的事务模型。

一、两阶段提交、三阶段提交
这种分布式事务解决方案目前在各种技术平台上已经比较成熟:javaee架构下面的jta事务(各应用服务器均提供了实现,tomcat除外)。
目前两阶段提交、三阶段提交存在如下的局限性,并不适合在微服务架构体系下使用:
1)所有的操作必须是事务性资源(比如数据库、消息队列、ejb组件等),存在使用局限性(微服务架构下多数使用http协议),比较适合传统的单体应用;
2)由于是强一致性,资源需要在事务内部等待,性能影响较大,吞吐率不高,不适合高并发与高性能的业务场景;
二、sagas长事务
在sagas事务模型中,一个长事务是由一个预先定义好执行顺序的子事务集合和他们对应的补偿子事务集合组成的。典型的一个完整的交易由t1、t2、......、tn等多个业务活动组成,每个业务活动可以是本地操作、或者是远程操作,所有的业务活动在sagas事务下要么全部成功,要么全部回滚,不存在中间状态。
sagas事务模型的实现机制:
1)每个业务活动都是一个原子操作;
2)每个业务活动均提供正反操作;
3)任何一个业务活动发生错误,按照执行的反顺序,实时执行反操作,进行事务回滚;
4)回滚失败情况下,需要记录待冲正事务日志,通过重试策略进行重试;
5)冲正重试依然失败的场景,提供定时冲正服务器,对回滚失败的业务进行定时冲正;
6)定时冲正依然失败的业务,等待人工干预;
sagas长事务模型支持对数据一致性要求比较高的场景比较适用,由于采用了补偿的机制,每个原子操作都是先执行任务,避免了长时间的资源锁定,能做到实时释放资源,性能相对有保障。
sagas长事务方式如果由业务去实现,复杂度与难度并存。在我们实际使用过程中,开发了一套支持sagas事务模型的框架来支撑业务快速交付。
开发人员:业务只需要进行交易编排,每个原子操作提供正反交易;
配置人员:可以针对异常类型设定事务回滚策略(哪些异常纳入事务管理、哪些异常不纳入事务管理);每个原子操作的流水是否持久化(为了不同性能可以支持缓存、db、以及扩展其它持久化方式);以及冲正选项配置(重试次数、超时时间、是否实时冲正、定时冲正等);
sagas事务框架:提供事务保障机制,负责原子操作的流水落地,原子操作的执行顺序,提供实时冲正、定时冲正、事务拦截器等基础能力;
sagas框架的核心是ibusinessactivity、iatomicaction。ibusinessactivity完成原子活动的enlist()、delist()、prepare()、commit()、rollback()等操作;iatomicaction主要完成对状态上下文、正反操作执行。
限于文章篇幅,本文不对具体实现做详述;后面找时间可以详细介绍基于sagas长事务模型具体的实现框架。
sagas长事务需要交易提供反操作,支持事务的强一致性,由于没有在整个事务周期内锁定资源,对性能影响较小,适合对数据要求比较高的场景中使用。
三、补偿模式