1. CAP定理
1.1 概念说明
consistent
:一致性,指数据的一致性。availability
:可用性partition tolerance
:分区容错性,发生故障的时候依然能够对外提供服务分布式系统中,三个要素最多选择两个,且
partition tolerance
一定会被选中1.2 一致性类型
强一致性:修改数据,后续的每个请求都能且必须拿到修改后的数据
- 弱一致性:修改数据,后面的请求一部分能拿到,一部分拿不到,最后进化为—>最终一致性
最终一致性:在可接受的时间里面,最终所有的请求都能拿到修改后的数据
1.3 CA、CP、AP分析
CA
:满足一致性,可用性,一般来说都是以单体存在的集群架构,扩展性不高,且都是关系型数据库CP
:满足一致性,分区容错性的系统一般来说,性能不会很高;例如dubbo
-
2. ACID原理
2.1 事务的四大特性
atomicity
:原子性,事务中的操作要么做,要么都不做consistency
:一致性,系统必须处在强一致的状态下isolation
:隔离性,一个事务的执行不能被其它事务所干扰durability
:持久性,一个已提交的事务对数据库中数据的改变是永久性的2.2 结论
它强调的是一致性,要么全成功,要么全不成功,所有用户看到的数据都是一致的
传统的数据库都有
ACID
的特性,它在CAP
理论中保证的是CA
3. BASE原理
3.1 特性介绍
basically available
- 基本可用,指在分布式系统出现故障的时候,允许损失部分可用性,保证核心链路可用
- 服务降级就是一种基本可用的体现
soft state
- 软状态,指允许系统出现中间状态,而中间状态不会影响整个系统可用性
- 分布式存储中一般一份数据存在多个副本,允许多个副本数据同步的延时就是软状态的体现
eventual consistency
在分布式事务的解决方案中,它都是依赖于
ACID
和BASE
模型实现的- 基于
ACID
模型- 基于
XA
的两阶段提交 - 事务补偿机制
(TCC)
- 基于
- 基于
BASE
模型- 而基于本地消息表和基于
MQ
的最终一致性方案都是通过BASE
原理实现的
- 而基于本地消息表和基于
-
5. 基于XA协议的两阶段提交
5.1 原理解析
它是由
X/Open
组织提出的分布式事务的规范- 由于一个
事务管理器(TM)
和多个资源管理器(RM)
组成 - 事务管理器就是程序中的数据源,资源管理器是具体的数据库
- 提交分为两个阶段:
准备阶段(prepare)
和提交阶段(commit)
- 所有的
RM
先准备,然后通知TM
,然后由TM统一的发出commit
指令 -
5.2 使用及注意事项
它保证了数据的强一致性
- 提交阶段出现问题,事务出现不一致,需要人工干预,例如写异常处理…
- 效率低下,性能与本地事务至少相差十倍
- 支持
MySQL 5.7
以上均支持XA
协议MySQL Connector 5.0
以上均支持XA
协议
- 它只能解决单个服务使用多个数据源的问题
- 例如:积分在用户库,订单在订单库,用户使用积分购买商品的流程发生异常
无法解决多个微服务之间的事务问题
-
5.3 XA分布式事务的实现
5.3.1 基于Atomikos的实现
在Java
系统中,数据源基本上采用的Atomikos数据源
做分布式事务,它就是充当TM
的角色,具体的实现查看视频即可:https://class.imooc.com/lesson/1237#mid=296185.3.2 MtCat配置分布式事务
-
不过滤 = 支持
- 在
server.xml
配置:<property name="handleDistributedTransactions">0</property>
- 配置属性说明
0
:不过滤分布式事务1
:过滤分布式事务(如果分布式事务内只涉及全局表,则不过滤)2
:不过滤分布式事务,但是记录分布式事务日志 ```sql — 首先关闭事务的自动提交 set @@autocommit = 0;
— 开启XA的事务 set xa = on;
— username字段只有两位,插入一个长的字符串,模拟异常
insert into user
(id,username) values(1,”奇数”),(2,”偶数ssss”);
— 提交事务 commit;
— 项目连接MyCat之后,只要开启分布式事务,然后出现异常它会自动支持的 ```
5.3.3 Sharding-Jdbc配置分布式事务
6. 事务补偿机制
- 简称TCC
- 针对每一个操作,都要注册一个与其对应的补偿(撤销)操作
- 在执行失败的时候,再调用补偿操作,撤销之前的操作
- 说白了就是出错了,调用补偿接口
- 补偿接口也会出现失败?
- 可以提供重试的次数,只要保持这个接口的幂等性即可
- 重试依然失败,则保存到数据库,人工补偿
- 也可以借助第三方工具,比如:
SEATA
。它把所有回滚的sql都记录在数据库中,并且标识是否执行成功。这样即使失败了,也可以再执行
- 优点:逻辑清晰,流程简单
- 缺点:数据一致性比XA还差,可能出错的点比较多
TCC属于应用层的一种补偿方式,程序员需要写大量的代码
采用BASE原理,保证事务最终一致性
- 在一致性方面,允许一段时间内不一致,但是最终会一致
- 将本事务外的操作,记录在消息表中
个人理解的整体流程
模拟下单扣减金额的业务流程
- 下单之后产生一笔订单,当前订单的状态是
未支付
- 调用支付服务的支付接口,客户支付50元,在支付服务上生成一条支付记录和消息记录
- 并且消息记录的状态是1、重试次数是0,代表还没有回调订单服务提供的修改订单状态的接口
- 定时任务不断轮询消息表,调用上游订单服务的接口,修改订单状态
可以使用原生的redis分布式锁,因为它是非阻塞的,直接返回错误