什么是分布式事务
指事务的操作位于不同的节点上,需要保证事务的 AICD 特性。
例如:你下单,要走订单服务和库存服务,如何确保事务的正确执行
如何解决
理论依据
AICD:
事务具有4个特征,原子性,一致性,隔离性,持久性
原子性:要么都执行,要么都不执行
一致性:事务不能不一部分执行成功,一部分执行不成功,导致数据不一致
隔离性:一个事务要操作的数据,不要被另一个事务同时操作
持久性:一但事务提交,那将永久修改数据库的数据
CAP:
c:一致性:所有节点存入数据,返回响应
a:高可用:某个节点存入数据,返回响应
p:分区容错性:某一个节点挂了,还可以有其他节点可以使用
BASE
BA:基本可用:出现错误,还可以对外提供服务
s:软状态:中间状态
e:数据一致性,中间状态存在有时间期限,一道期限,必须保证数据一致性
技术
2pc(二阶段提交)
第一阶段:让每个参与者执行sql,如果都执行成功,则到第二阶段提交,如不成功,进行回滚
第二阶段:进行commit操作(这一部分无法解决commit时,有服务出现错误的情况)
缺点:
- commit的时候发生网络故障(某一服务没有commit),导致数据不一致
- 再等待所有参与者响应时,所有的参与者都是阻塞状态
TCC(两阶段补偿提交)
重点:
3个方法(try,确认,补偿),字段新增了一个中间状态和一个预留字段(用于存减了多少库存,或者减去/加上某某值)
例子:我们买了2件衣服
物品id | 物品名称 | 库存 | 状态 | 预留字段 |
---|---|---|---|---|
1 | 衣服 | 20 | 未更新 | 0 |
首先我们先调用try方法,作用:看库存够不够,把这一行数据的状态改为更新中,再预留字段中存入我们要减的库存
物品id | 物品名称 | 库存 | 状态 | 预留字段 |
---|---|---|---|---|
1 | 衣服 | 20 | 更新中 | 2 |
更新状态就不能被其他操作
然后执行sql,commit,如果都成功了,调用确认方法,进行状态的更新,预留字段的值变为0
物品id | 物品名称 | 库存 | 状态 | 预留字段 |
---|---|---|---|---|
1 | 衣服 | 18 | 已更新 | 0 |
如果有一个没有执行成功,那么就会调用补偿方法,进行状态的更新,预留字段的值变为0
物品id | 物品名称 | 库存 | 状态 | 预留字段 |
---|---|---|---|---|
1 | 衣服 | 20 | 已取消 | 0 |
rabbitmq
重点:
- 保证生产者能将消息传到mq(消息确认机制)
- mq能够正常的被生产者消费(消息确认机制,重试机制)
- 不能被重复消费(将消息id放到redis中)
最终实现数据最终一致