diff --git a/Solution.md b/Solution.md index cf7b7ad..fe26f44 100644 --- a/Solution.md +++ b/Solution.md @@ -5694,7 +5694,54 @@ Confirm阶段一般需要各个服务自己实现Confirm逻辑: - 用mq消息异步传递子事务状态,最终达到全局事务的完成 - 特点是由发起方决定是否回滚,也就是说只要发起者成功,后续的子事务基本都能成功。比如刷卡后,增加消费积分 +**伪代码:** + +```java +执行(事务主题, transId, 参与者){ + name = 参与者.名称() + + mq.setMsg(事务主题, transId, name, 'ping') + mStatus = 参与者.prepare(); + mq.setMsg(事务主题, transId, name, 'prepare') + if mStatus: + excuted = 数据库是否提交(transId, name) + if not excuted: + 参与者.commit() + mq.setMsg(事务主题, transId, name, 'commit') + else: + 参与者.rollback() + mq.setMsg(事务主题, transId, name, 'rollback') +} + +发起者A{ + transId = getTransactionId() + 执行(事务主题X, transId, 参与者A) + name = 参与者A.名称() + mq.订阅事件(事务主题X, name).触发函数(e){ + transId = e.transacationId; + 定时任务(事务主题X, transId, name) + if e.message == 'commit': + //启动下一个兄弟事务 + mq.setMsg(事务主题X, transId, 参与者B名称, "wake up and work") + else if e.message == 'rollback': + mq.delMsg(事务主题X, transId) + } +} +参与者B{ + name = 参与者B.名称() + mq.订阅事件(事务主题X, name).触发函数(e){ + transId = e.transacationId; + 定时任务(事务主题X, tranId,name) + if e.message == 'wake up and work': + 执行(事务主题X, transId, 参与者B) + else if e.message == 'commit': + mq.delMsg(事务主题X, transId) + else if e.message == 'rollback': + //人工处理,因为一般都能执行成功 + } +} +``` **优/缺点:** @@ -5829,10 +5876,49 @@ Confirm阶段一般需要各个服务自己实现Confirm逻辑: ## Sagas事务模型 +**原理:(消息)异步 + TCC(部分)** + + + Saga事务模型又叫做长时间运行的事务。其核心思想是**「将长事务拆分为多个本地短事务」**,由Saga事务协调器协调,如果正常结束那就正常完成,如果**某个步骤失败,则根据相反顺序一次调用补偿操作**。 +**伪代码:** + +```java +执行代码{ + 总事务开始() + + new Thread( + aStatus = 参与者A.冻结资源().commit() + if aStatus: + 参与者A.扣除资源().commit() + else + 参与者A.解冻资源().commit() + ).start() + + new Thread( + bStatus = 参与者A.冻结资源().commit() + if bStatus: + 参与者B.扣除资源().commit() + else: + 参与者B.解冻资源().commit() + ).start() +} + +自行实现的定时任务{ + if 全部参与者已完成事务: + if 全部扣除commit成功: + 总事务成功() + else + 已扣除资源退还() + 总事务失败() +} +``` + + + ## Seate **XA和Seata区别**