一、分布式架构
1.1 集中式、分布式、微服务与集群
1.1.1 相关概念及特点
集群:
- 多台服务器运行相同的服务
- 具有伸缩性,横向扩展,动态扩容
- 高可用性,抗故障能力强
- 负载均衡,动态分配负载
- 高性能:通过提高单位时间内执行的任务数提高效率
分布式:
-
多台机器的服务组成一个系统,运行不同的服务
-
通过缩短单个任务的执行时间提高效率
微服务: 一个系统拆成多个服务,每个服务都可以独立运行(不需要多台机器,可以部署在单机器)
集中式: 整个系统部署在一台机器上
1.1.2 分布式环境的各种问题
- 通信异常:节点之间网络通信容易发生问题,消息丢失和消息延迟非常普遍
- 网络分区:两个节点之间无法互相通信,就发生了网络分区
- 三态:成功、失败、超时。两种超时现象发送发无法确认请求是否被正常处理。
- 请求未发送到接收方,发送过程中发生了丢失现象
- 接收方接收到请求,相应过程中发生了消息丢失现象
- 节点故障
1.2 从ACID到CAP/BASE
单机可以完全依赖数据库本身的功能实现事务,但分布式场景涉及多数据库,就需要分布式事务理论。
1.2.1 事务的ACID
事务是对系统中数据进行一系列操作的逻辑单元。
事务的四个特征:
- 原子性 Atomicity:一次操作要么成功,要么失败
- 一致性 Consistency:从一个一致性状态转化为另一个一致性状态
- 隔离性 Isolation:事务之间的操作不能相互干扰
- 持久性 Durability:事务一旦提交,对数据修改导致的变更是永久性的
1.2.2 CAP定理
一个分布式系统不可能同时满足一致性(Consistency)、可用性(Availability)和分区容错性(Partition tolerance),最多同时满足两个
一致性(Consistency):
指数据在多个副本中是否能保持一致的特性。第一个节点进行更新后,对第二个节点更新失败,这时就发生了分布式数据不一致的情况。
对一个数据项进行更新后,所有用户都能取到最新的值,这样的系统被认为具有强一致性。
可用性(Availability):
系统能够在有限的时间内返回结果。
分区容错性(Partition tolerance):
分布式系统遇到任何网络分区故障的时候,都能保证对外提供满足一致性和可用性的服务,除非整个网络都发生了故障。
这里提供一致性和可用性不代表分布式系统同时满足了CAP,而是指当前给用户提供服务的子分区满足了CA。可能另一部分分区处于不可用状态。
满足的定理 | 说明 |
---|
满足CA,放弃P | |
满足CP,放弃A | |
满足AP,放弃C | |
系统架构设计师将精力花在如何根据业务特点,在一致性和可用性中间寻找平衡。
1.2.3 BASE理论
BASE是对CAP中一致性和可用性权衡的结果。其核心思想是:即使无法做到强一致性,但每个应用可以根据自身业务特点达到最终一致性。
基本可用(Basically Available):出现故障时允许损失部分可用性
软状态(Soft state):允许系统中数据副本之间数据同步过程存在延时
最终一致性(Eventually consistent):经过一段时间后,数据最终是一致的,不需要实现强一致性。
- 因果一致性
- 读己之所写
- 会话一致性
- 单调读一致性
- 单调写一致性
二、一致性协议
二阶段提交协议、三阶段提交协议和Paxos算法
2.1 2PC (Two-Phase Commit) 二阶段提交
绝大部分的关系型数据库都是采用二阶段提交协议完成分布式事务处理
2.1.1 协议说明
阶段一:提交事务请求
也被称为投票阶段,各个参与者投票表明是否继续执行事务提交操作。
- 事务查询: 协调者向所有参与者发送事务内容,询问是否可以执行事务提交操作,等待各参与者的相应
- 执行事务: 各参与者结点执行事务操作,并将undo和redo信息记入事务日志
- 响应结果: 参与者根据操作结果成功与否给协调者响应
阶段二:执行事务提交
协调者根据各参与者反馈情况决定最终是否进行事务提交操作。包含两种可能
执行事务提交: 假如所有参与者都反馈成功,则执行事务提交
- 发送提交请求: 所有响应都是成功则会向参与者发出Commit请求
- 事务提交: 参与者接收Commit请求后会执行提交操作,提交之后释放在整个事务执行期间占用的事务资源
- 返回事务提交结果: 提交后,向协调者发出Ack消息
- 完成事务: 协调者接收到Ack消息后,完成事务
中断事务: 任何一个参与者向协调者反馈失败,或者超时无响应,则会中断事务
- 发送回滚请求: 协调者向参与者发出Rollback请求
- 事务回滚: 参与者接收到Rollback请求后,利用undo信息进行回滚,回滚后释放事务占用的资源
- 反馈事务回滚结果: 回滚后向协调者发出Ack消息
- 中断事务: 协调者接收到Ack消息后,完成事务中断
2.2.2 优缺点
优点: 原理简单,实现方便
缺点: 同步阻塞、单点问题、脑裂、太过保守。该协议没有较完善的容错机制,任意结点失败都会导致整个事务的失败。
- 同步阻塞: 每一阶段的执行过程中,参与者会互相等待对方完成后,才能进入下一阶段
- 单点问题: 协调者出现故障,分布式事务就会出现问题。比如二阶段协调者故障,所有参与者会一直锁定事务资源。
- 数据不一致: 二阶段即事务提交的时候,只有部分参与者接收到commit请求(网络问题、协调者中途崩溃),导致了数据不一致。
- 太过保守: 参与者故障导致协调者无法获取所有参与者响应时,只能依靠超时策略判断是否中断事务。
2.2 3PC(Three-Phase Commit) 三阶段提交
2.2.1 协议说明
3PC是2PC的改进版,将2PC的第一阶段(提交事务请求)过程分成两部分。
阶段一:CanCommit:
- 事务询问: 向所有参与者发送包含事务内容的commit请求,询问是否可以执行事务的提交操作,等待参与者的响应
- 响应询问: 参与者判断自身能否顺利执行事务,响应相应信息
阶段二:PreCommit:
根据CanCommit的响应结果,该阶段有两种可能。
执行事务预提交:所有参与者反馈成功
- 发送预提交: 发送preCommit请求,进入准备阶段Prepared
- 事务预提交: 参与者收到请求后,执行事务操作,将Undo和Redo信息记录到事务中
- 响应询问: 各参与者向协调者反馈事务执行的响应
中断事务:任意参与者反馈是失败响应或者超时,则会中断事务
- 发送中断请求: 协调者向所有参与者发出abort请求
- 中断事务: 参与者收到abort请求,或者等待超时,则会中断事务
阶段三:DoCommit:
根据PreCommit的结果,处在两种可能
执行提交
- 发送提交请求: 协调者收到所有参与者的ack响应,从预提交状态转换为提交状态,向所有参与者发送doCommit请求
- 事务提交: 参与者收到doCommit请求或超时等待(会有数据不一致的问题)后,执行事务提交操作,提交结束释放事务资源
- 响应结果: 完成事务提交后,向协调者发送Ack消息
- 完成事务: 协调者接受所有参与者反馈的Ack消息后,完成事务
中断事务:任意参与者反馈是失败响应或者超时,则会中断事务
- 发送中断请求: 协调者向所有参与者发出abort请求
- 事务回滚: 参与者收到abort请求,利用阶段二记录的Undo信息执行事务回滚操作,并在完成回滚后释放事务资源
- 响应结果: 完成回滚后,发送Ack消息
- 中断事务: 协调者接收Ack消息后,会中断事务
2.2.2 优缺点
优点:
缺点:
- 处于三阶段时发生了异常(协调者崩溃、网络通信异常、网络分区),参与者超时后仍然提交事务,可能导致数据不一致
三、事务分类:刚性事务与柔性事务
3.1 刚性事务
遵循ACID原则,具有强一致性。相当于CP
1. WAL(Write ahead logging)预写日志
现代数据库的通用做法。修改提交前先写入log文件
2. Shadow Paging 影子分页
3. XA协议(2PC、JTA、JTS、3PC、AT)
3.2 柔性事务
遵循BASE理论,具有最终一致性。 相当于AP
1. 补偿性:都是同步的
2. 通知型:都是异步的
四、 Seata四种事务模式:XA、TCC、AT、SAGA
这里不写Seata的实现,只讲四种模式的理论。
4.1 XA
首先XA是一个协议,定义了角色和相关接口。Seata依据XA协议提供了XA模式。
DTP模式定义TM和RM之间通讯的接口规范叫XA,简单理解为数据库提供的2PC接口协议,基于数据库的XA协议来实现的2PC又称为XA方案。
分布式事务DTP模型定义的角色如下:
- AP:即应用程序,可以理解为使用DTP分布式事务的程序,例如订单服务、库存服务
- RM:资源管理器,可以理解为事务的参与者,一般情况下是指一个数据库的实例(MySql),通过资源管理器对该数据库进行控制,资源管理器控制着分支事务
- TM:事务管理器,负责协调和管理事务,事务管理器控制着全局事务,管理实务生命周期,并协调各个RM。全局事务是指分布式事务处理环境中,需要操作多个数据库共同完成一个工作,这个工作即是一个全局事务。
我理解Seata的XA是每个服务在一阶段开始事务,在二阶段进行提交。在提交前数据库会一直持有事务资源
4.2 TCC
侵入式的分布式解决方案,需要在系统代码中实现 try、confirm、cancel的业务逻辑。支持把 自定义的分支事务纳入到全局事务的管理中。
- Try:对业务资源的检查并预留;
- Confirm:对业务处理进行提交,即 commit 操作,只要 Try 成功,那么该步骤一定成功;
- Cancel:对业务处理进行取消,即回滚操作,该步骤回对 Try 预留的资源进行释放。
特点:
- 侵入性比较强,并且需要自己实现相关事务控制逻辑
- 在整个过程基本没有锁,性能较强
TCC和AT区别
TCC与2PC比较:
- TCC位于业务服务层而非资源层
- TCC没有单独的准备(Prepare)阶段,Try操作兼备资源操作与准备能力 Try操作可以灵活选择业务资源的锁定粒度(以业务定粒度)
- TCC有较高开发成本
4.3 AT
AT模式是Seata提供的一种无侵入的分布式事务解决方案,数据库层面的执行和提交作为第一阶段,Seata框架自动完成第二阶段的提交和回滚操作
两阶段提交的变更:
- 一阶段:每个本地事务直接提交,释放锁、事务、连接资源
- 二阶段:
- 分支提交:异步删除回滚日志记录
- 分支回滚:基于回滚日志进行反向补偿更新
特点:
- AT默认隔离级别为读未提交
- 性能比XA高(减少了本地锁持有时长),只在第一阶段获取数据库的锁,提交后释放。
如何避免脏写:
分布式事务第一阶段结束释放了本地锁。那么是如何避免二阶段过程中其他事务操作无本地锁的数据。
Seata引入全局锁
4.4 Saga
Seata提供的长事务解决方案,所有子业务都不参与整体事务,回滚补偿由TM(事务管理者,调用子业务的应用)完成。因此可以不修改子业务系统代码。
参考