数据库
首页 > 数据库> > 基于 MySQL 和 DynamoDB 的强一致性分布式事务实践

基于 MySQL 和 DynamoDB 的强一致性分布式事务实践

作者:互联网

点击“终码一生”,关注,置顶公众号

每日技术干货,第一时间送达!

 

 

在单体应用向微服务架构转型的过程中,本地事务已不再满足系统一致性需求,为了解决这一问题,前人在对性能和数据一致性反复权衡的过程中总结了许多典型的协议和算法,各有优劣。本文我们将深入探讨 Freewheel 如何实现无单点故障的可扩展分布式事务实现模型。

 

 

1、为什么需要分布式事务?

 

当应用程序有严格的数据一致性要求时,ACID 事务是必须的,如果一个事务涉及的所有操作能够放在一个服务内部,且共用一个数据库,那么只用在一个方法里同一个事务下操作数据库即可。然而为了提升系统整体的可靠性,方便各个模块独立演化,系统从单体应用演进为微服务架构。随着数据体量的增长,数据源也从 MySQL 扩展到关系型数据库 Amazon Aurora 和 NoSQL 数据库 (Amazon DynamoDB),基于多样化索引和查询数据的需求,引入了搜素引擎 (ApacheSolr 和 ElasticSearch ) ,多服务交互、多数据源并存产生了分布式事务。

 

Freewheel 分布式事务应用场景有三个:

 

综合考虑 Freewheel 的业务需求后,我们实现了多引擎数据库分布式事务。

 

 

2、多引擎数据库分布式事务设计

 

Freewheel 分布式事务方案主要设计目标如下:

 

数据强一致性:确保该事务范围内的所有操作都可以全部成功或者全部失败,事务具有原子性、一致性、隔离性、持久性 4 个特性。

系统高可用:遵循“design for failure”的设计原则,硬件层面,采用服务节点多 region 多 AZ 部署和节点故障快速自恢复的策略来保证系统的高可用。软件层面,设计 failover 机制应对服务异常。

 

可扩展:应用 Auto Scaling 服务,它会基于设定的负载压力,自动进行扩展和缩容,来保证服务正常运行。

 

易用性:分布式事务应用 API:易学,易懂,易记,系统设计上无业务侵入,没有额外的编码或测试工作。

 

 

3、多引擎数据库分布式事务技术选型

 

常见分布式事务解决方案对照表:

 

图片

 

结合 Freewheel 强一致性业务需求,多数据源分布式事务将由 XA、2PC 和 Seata 这些解决方案组合而成。

 

 

 

4、多数据源分布式事务解决方案

 

架构解析

 

Freewheel 分布式事务依托在 Freewheel 数据访问层中间件 (DAL) 上,这个中间件是由 Freewheel 平台团队自主研发的,它的目标是为上游应用提供更好的数据访问,为下游数据源提供更好的保护。为了方便描述,下文均用 DAL 来作为 Freewheel 数据访问层中间件的简称。

 

分布式事务由这三个组件来协商处理:

 

 

为了预防死锁,并且减少 DAL RM 和 TC 之间的 交互,降低对 TC 的依赖,同一个分布式事务操作放在同一个 DAL 节点,由此,DAL RM 可以方便的在单节点控制和协调分支事务,完成全局事务的提交和回滚。

 

以多服务,不同数据源 (Aurora 与 DynamoDB) 为例,描述 Freewheel 分布式事务过程。

 

 

图片

 

数据访问层资源管理器 (DAL RM) 实现

 

基于业务需求,DAL 分布式事务支持的数据源为 MySQL 和 AWS DynamoDB,下面章节阐述了这两个数据源 ACID 技术实现。

 

分布式事务设计中新建了事务控制表、事务记录表、索引表及业务镜像表:

 

Aurora/MySQL

 

采用 MySQL XA 2PC 来保证 ACID,原因如下:

 

 

这个时序图描述了 RM 对 MySQL 事务的工作流程:

 

图片

 

一个事务操作,由同一个 DAL RM 处理,相同 DB 下业务事务处理,放在一个 XA 操作里:

 

SQL CRUD 语句应该使用触发行锁的索引操作,否则会触发表锁,影响系统吞吐量。

 

AWS DynamoDB

 

DynamoDB 提供了本地事务接口 TransactGetItems 和 TransactWriteItems, 它等效于 MySQL 批量操作,对于相互间有上下文或者依赖的操作并不可用,这限制了它在应用中的使用场景,详细信息请参考 TransactGetItems 和 TransactWriteItems。

 

DynamoDB 本身没有分布式事务机制,DAL 结合 DynamoDB 功能属性,对提供的插入、更新、删除和查询接口,设计 2PC 机制 来满足 DynamoDB 的 事务属性。

 

下表显示了分布式事务操作 (DisTxDAL) 和其他操作之间的隔离级别。

 

图片

 

更新接口实现方法

 

一阶段

 

图片

 

 

二阶段

 

插入接口实现方法

 

一阶段

 

二阶段

 

删除接口实现方法

 

一阶段

 

二阶段

 

查询接口实现方法

事务进行中的数据含有事务属性信息,xid 表示事务全局事务 ID, operation 表示事务操作接口 create、update、delete,这里 item 表示业务数据元素。

 

图片

 

基于业务数据变更表及写接口实现方法,实现了在读提交与读未提及查询方法:

 

  1. 判断记录是否含有事务属性,如果无,返回记录,否则到步骤 2

  2. 判读隔离级别,如果读提交,步骤 3,如果读未提交,步骤 5

  3. 记录事务操作是 create, 返回空,否则如果是 delete,去除事物属性信息,然后返回,否则步骤 4

  4. 本地事务原子地读取镜像表与业务表,如果镜像表值存在,返回,否则返回业务表值,都不存在返回空

  5. 如果记录事务操作是 delete,返回空,否则返回记录

 

数据访问层事务管理器 (DAL TM) 实现

 

为了方便用户使用,分布式事务 API 里封装了与事务协调器及 DAL 资源管理器的交互过程,交互过程对应用是透明的,下面是分布式事务 API:

 

type DistributedTransApi interface {
        DisTxDAL(ctx context.Context, fn TranFunc) error
}
type TranFunc func(ctx context.Context) error

 

微服务之间,微服务与数据库访问层之间采用 google rpc 调用,服务之间关键数据都是基于 context metadata,如果经过两层服务交互, 就会导致 context metadata 丢失。举例来说,A 服务调用 B 服务,B 服务调用 C 服务,那么 C 服务就会缺失 A 服务 context metadata,针对这种情况,DAL 提供了通用函数用于提取 DAL 相关的元数据,供应用方按需添加。

 

func ExtractDalMetadata(ctx context.Context) (metadata.MD, error)

 

数据访问层事务协调器 (DAL TC) 实现

 

协调器主要功能点:

 

 

分配事务 XID

全局分配唯一事务 ID,供 DAL TM 获取,此数据需要在同一事务的业务服务间传输共享。

 

事务协调

维护全局事务的运行状态,负责协调和驱动全局事务的提交或回滚。

 

故障转移

DAL TC 是 HA 多节点实例,引入 ETCD leader 选举机制来保证只有一个 TC 实例承担 failover 功能,详细信息在系统高可用章节软件层面 failover。

 

系统高可用

 

硬件层面

为了预防硬件故障对高可用的影响,DAL,TC 和 ETCD 服务均是多 Region 多 AZ 部署,并且基于服务的特性配置了相应的服务策略:

 

 

美东美西均部署相应服务作为服务灾备策略,下图是美东地区的解释图(美西类似)。

 

图片

 

 

软件层面 Failover

 

在 DAL 应用或者业务应用遇到异常退出时,软件层面 Failover 机制是为了能不发生死锁,并且继续处理未完成分布式事务,实现方法如下:

 

 

5、未来展望

 

Freewheel 强一致性分布式事务未来会支撑更多的数据源,如 Redis、Solr 和 ElasticSearch 等,目前的数据库访问层 API 是基于 gRPC,这对数据库访问层使用方带来了一定技术语言限制,未来会探究 GraphQL 在数据库访问层分布式事务应用的可行性。

 

 

PS:防止找不到本篇文章,可以收藏点赞,方便翻阅查找哦

标签:事务,服务,DAL,数据源,回滚,DynamoDB,MySQL,分布式
来源: https://www.cnblogs.com/zhongmayisheng/p/15750126.html