SpringCloudAliBaBa 学习
服务的注册与发现
分布式事务
使用场景 同一个事务对两个数据库操作,事务肯定是会失效的 因为一个事务就是一个数据库连接,不同的连接就是不同的事务
Seata 是什么?
Seata是一款分布式事务解决方案,用AT模式是阿里推荐的
事务模式:TCC、SAGA、XA
常见分布式事务解决方案
1、seata 阿里分布式框架
2、消息队列
3、saga
4、XA
这四种都是 两阶段(2PC)的协议:完成整个分布式事务需要两个步骤完成
2PC 协议?
预处理Prepare
参与方 数据库或应用
提交Commit
处理流程:一、预处理
询问:协调者向各个参与者 发起询问 是否可以执行事务操作,然后等待各个事务响应
执行:各个参与者收到协调者的事务请求后,执行事务操作,并将undo、redo信息 记录在事务日志表中
预处理sql执行任务是否满足条件(为什么这样设计:1、提交的话 对数据覆盖)
响应:如果参与者成功执行了事务并写入Undo、Redo信息,则向协调者返回yes响应,当然参与者也可能宕机 不响应。如果响应为No,则协调者触发回滚
二、提交/回滚机制
commit通知:请求协调者向所有参与者发送了Commit请求
事务提交: 参与者收到commit请求后,执行事务提交、提交完成后释放事务执行期间占用的所有资源
反馈结果:参与者执行事务提交后向协调者发送Ask响应(没用100%的成功率)
完成事务:接收到所有参与者的Ack响应后,完成事务提交
2PC的问题
1、参与者在等待协调者发送指令时 其实是在等待其他参与者的响应。在此过程中其参与者是不能做其他操作的 也就是阻塞了
2、协调者可能会挂掉
3、数据不一致:如果参与者之一宕机,则无法向协调者发送消息 就无法判断事务成功失败
AT协议(Auto Transaction)
AT 模式是一种无侵入的分布式事务解决方案、我们只需要编业务SQL就行
一阶段:
Setta会拦截"业务SQL",提取元数据,在数据被更新前,update user set name ="李五" where name ="李四"
将其保存为befor image(select * from user where nbame ='李四'。
再业务数据更新之后,再将其保存为"after image" 最后生成行锁。以上操作全部在一个数据库内完成,保证操作的原子性
二阶段:提交
提交的话 因为业务sql在阶段一已经提交至数据库,所以seata框架只需要将保存的快照数据和行锁删掉完成数据清理就行了
回滚:
数据校验:after image 和数据库对比(防止脏数据)
还原数据:before image -> 逆向SQL ->数据还原
删除中间数据:见提交
TCC模式
特点
1、侵入较强
2、在整个过程中基本上没有锁 性能较强
TCC框架: BeyeTCC、TCC-transaction
订单服务
阶段一:中间事务协调->try(比如原本修改订单状态为已完成,这里修改为"下单中" 进行锁定防止其他线程侵占)
阶段二:try->confirm() try没问题->入库把状态改为真实状态 已完成
阶段三:cancel 回滚 状态改为 未支付
库存服务:
阶段一:协调方调用try 修改库存熟练
阶段二:如果操作成功-> 进行真实提交
阶段三 如果回滚:则设置恢复上锁的资源数量
可靠消息的最终一致性方案(RocketMQ)
订单服务:
阶段一:1、try:sendMQ("预备消息")-> RocketMQ
阶段二:1、修改订单状态2、senCommit("发送确认消息")->RocketMq -> 扣减库存
如果确认消息commit发送失败,RocketMq对服务进行回查 如果回查15次后没有回应则 删除消息(对该消息不进行消费)。如果库存扣减失败 也会进行消息的重试15次。如果失败则通知我们手动补偿
阶段三: