一、背景
随着微服务架构的演进,单体应用按照服务维度进行拆分,组织架构也随之演进以横向、纵向维度拆分;导致了原来调用一个服务的一个接口就完成的功能,现在需要协同调用多个服务的多个接口才能完成。原来在一个库中就完成的功能,现在可能要涉及多个库的多张表,通常还会有多种存储介质一起协作以支撑数据存储;而这些情况下传统的本地事务不能保证数据的一致性。
以下图购买商品下单业务为例,下订单由订单服务、账户服务和库存服务 3 个服务来完成。
本地事务只能保证每个服务各自的本地事务,比如库存服务 DB 操作异常,其通过本地事务回滚后库存数据无异常,但订单和账户的记录并未回滚,因为他们并不知道库存异常了,这便是典型的分布式数据一致性问题。
二、现状
在生产环境中设备、程序等是不可靠的,若它们发生意外则会出现数据不一致的情况;在对数据的一致性要求高的业务场景中,若缺少有效工具的辅助,则常常需要通过如客诉、人工抽检核对等方式来发现问题,之后再交给程序员通过人工智能来排查、修复;这种方式虽也能解决问题,但从时效和人力两方面看都不高效,同时也拉低了服务质量。
虽然 BASE 论文基于 CAP 定理分析并表述了分布式系统追求高可用的场景下不得不弱化强一致性的观点,并对众人产生了深远的影响,但并不能理解为要降低对一致性的要求,尤其是在某些特殊业务场景中,数据容易出现非预期的不一致或高延迟的不一致时,会给客户带来极其不好的使用体验,严重时甚至导致运营无法推进、产品无法落地。所以需要重新审视数据一致性问题,它实际是与系统的可扩展性和高可用同等重要 是【基础 IT 架构】支撑业务高质量转型、升级的重点也是难点。
三、诉求
应对业务规模、数据规模的不断扩大,主流技术方案都是通过横向扩展节点以提高非热点数据的并发性能;而横向扩展节点的效果体现在如下 2 方面:
- 扩展功能节点:对应用进行微服务化改造。
- 扩展数据节点:增加数据分片如分库分表,使用混合存储如 mysql + ES 的组合。
微服务演进方案的优势很多,但同时也必然会带来业务数据不一致的问题,有些情况还让人特头疼。在之前很长一段时间,受分布式事务技术成熟度、业务的复杂性及实现性价比等多重因素的影响,关于该如何应对分布式业务数据一致性的这个难题,似乎分化成两种相对的观念:一种是困难太多、性价比不高,一致性保障让人有心无力,进而置之不理;另一种则是需迎难而上,各显神通,导致出现了许多有意思的变种实现,有些可能既不通用也不健壮。
从标准架构规范的大局来看,置之不理或各显神通这两种情况都非合理状态,实际上需要的是一套规范的、通用的、可靠的分布式事务解决方案,能够帮助开发者在分布式的环境下,既能保证业务数据的一致性,又不需要投入太多的资源用于业务数据一致性的开发维护,还能加快迭代速度保障项目交付。
四、选型
分布式事务解决方案通常分为两大类,其中一类是异步确保型,另一类是非异步确保型;异步确保型非本篇主题,暂且不提。重点探讨非异步确保型,在行业中开源的分布式事务解决方案的产品有Seata
、tcc-transaction
TX-LCN
Hmily
ByteTCC
EasyTransaction
等,它们各有特色后续会整理一篇稍详细点的能力对比介绍。从它们所提供方案的分类来说有:补偿型-TCC 、无侵入性-AT、强一致型-XA 、补偿性-SAGA 以及 LCN。Seata 的能力比较全面,所提供方案种类最多,而且社区活跃度最高。
Seata 从设计层面将事务参与者的角色分为 TC、RM、TM,事务的整体运转模型如上图,基于此模型,Seata 支持了TC、AT、XA、SAGA 这 4 种方案,能应对许多应用场景,个人感觉比较贴合日常分布式事务能力诉求的的是 TC 集群的高可用架构 以及 TCC 和 AT 这两种事务模式的能力。
1)TC 集群具有高可用架构
应用到集群是这样一个间接的关系:应用 -》事务分组 -》TC 集群,应用启动后所指定的事务分组不能变,可通过配置中心变更事务分组所属的 TC 集群,Seata 客户端监听到这个变更后,会切换到新的 TC 集群。
2)TCC 模式
- TCC 模式要求由业务侧通过编码实现 Try、Confirm、Cancel 3 个方法,TCC 的 Try 操作作为一阶段,负责资源的检查和预留;Confirm 操作作为二阶段提交操作,执行真正的业务;Cancel 操作作为二阶段回滚操作,执行预留资源的取消,使资源回到初始状态。
- 因为各阶段都由业务侧编码实现,所以就大大增加了灵活性,容易实现特定场景下的自定义优化和特殊功能开发。这个模式几乎能满足任何想要的事务场景,如补偿型、资源预留型以及消息事务型等。但也意味着开发的工作量比较大,对开发者的要求比较高。
- 无论有没有本地事务控制都可以使用该模式,与底层数据库事务实现不相关(无需 JDBC 支持)。
- Seata 对 TCC 模式实现的完整度比较高,可应对经典的空回滚、防悬挂和幂等控制这三个问题。
3)AT 模式
- 若把 TCC 模式类比成手动挡驾驶模式,那么 Seata 的 AT 模式就好比自动挡驾驶模式。AT 模式 是基于 DataSource 代理实现的,其核心思想就是由框架托管分布式事务:通过代理 DataSource ,拦截 SQL 执行,增强其执行逻辑,由代理侧加入额外的能力以完成分布式事务。
- 要求上下游分支事务都支持 JDBC,且所用的 SQL 需要框架能够支持,有一定的性能损耗,在应用层增加了全局锁(行级锁),高并发有热点数据的场景需斟酌。
- 在业务并发不高、逻辑复杂、对一致性要求较高的场景中特别有优势,只需要引入依赖后调整少量代码,方法上增加注解便可拥有完整的分布式事务的能力;这种场景下,特能体现 AT 模式难度低、效率高、更安全的特点。
基于以上评估,Seata 所兼备的 TC 高可用、 TCC 模式和 AT 模式特别符合一套规范的、通用的、可靠的分布式事务解决方案的诉求,能将分布式事务问题从业务中尽量剥离出来(AT模式剥离的比较彻底),作为一个独立的技术切面由专人管理运维(独立的服务端和模块化的客户端),提供简单、易用、高效、稳定的分布式事务解决方案,体现出以下价值:
- 架构复杂度降低:分布式事务这个切面的技术问题,全部由 Seata 所提供的服务能力来解决。
- 设计和开发成本减轻,加快交付和迭代速度:业务逻辑的设计和开发中,若采用 AT 模式,则无需考虑是否涉及分布式事务,是否需要做额外的准备,专注 SQL 编写实现业务逻辑即可,对业务 0 侵入 。
- 运营成本降低,保证业务数据准确度,以及出错时的自动回滚和及时通知
五、总结与预告
本篇介绍了微服务架构演进,必然带来数据不一致的问题,在一些特性场景下数据的一致性要求会很高,而大多数情况下对一致性的要求又不高,这些差异也导致了对分布式事务解决方案呈现两种相对的顾念,一种认为可以置之不理,一种则认为必须解决,在没有标准方案的情况下,很容易出现各显神通,做出的东西即不通用也不健壮。
这两种情况从标准架构规范的大局来看都非合理状态,实际上从公司技术架构管理的角度看,需要的是一套规范的、通用的、可靠的分布式事务解决方案,能够帮助开发者在分布式的环境下,既能保证业务数据的一致性,又不需要投入太多的资源用于业务数据一致性的开发维护,还能加快迭代速度保障项目交付。
从技术架构管理的角度看,需要一套规范的、通用的、可靠的分布式事务解决方案,帮助开发者在分布式的环境下,既能保证业务数据的一致性,又不需要投入太多的资源用于业务数据一致性的开发维护,还能加快迭代速度保障项目交付。
下一篇计划介绍在业务导向的主旨下,推进分布式事务解决方案-Seata的一些参考思路和建议。
下下一篇看大家有什么诉求。
五、最后说一句(请关注,莫错过)
如果这篇文章对您有帮助,或者有所启发的话,欢迎关注笔者的微信公众号【 架构染色 】进行交流和学习。您的支持是我坚持写作最大的动力。
参考并感谢
分布式事务 Seata 及其三种模式详解 | Meetup#3 回顾