请稍等 ...
×

采纳答案成功!

向帮助你的同学说点啥吧!感谢那些助人为乐的人

关于引入事务性消息&库存流水方案的必要性的疑问

老师好,

我对比了8-1节末尾的方案(我改动了一点)和到现在这节的方案,觉得(在不考虑本地处理线程莫名死掉的情况下,仅考虑异常)后者并没有解决前者的问题:

方案一链路(这里是把mq发送消息放到createOrder最后,不作为aftercommit执行):
app server:redis扣减——订单入库mysql——mq生产者发送消息
mq消费端-mysql:消费消息,mysql减库存
此时会有两个潜在的造成数据不一致的问题:
(1)app server&mq 生产端流程无异常(即返回下单成功),mq消费端失败,此时:redis正确,redis<mysql
(2)app server&mq 生产端流程在redis扣减成功后出现异常(即返回下单失败),此时:mysql正确,redis<mysql

方案二链路:
app server:controller初始化stocklog—— mq生产者预提交事务消息 — mq生产者事务监听器收到事务消息,执行本地事务( redis减库存 — mysql订单入库 ——stocklog修改为成功状态),根据执行情况决定是否发送——controller拿到最终发送决策,返回下单成功/失败

此时会发现上述的两个问题依然存在。

事实上我觉得这里的两阶段提交,mq生产者复查本地事务执行情况,在本地线程不会莫名死掉的情况下是没有必要的,方案一中代码一旦执行到mq生产者发送消息那一步就说明前置操作执行无误,默认决策是发送消息的。

所以这里觉得这个优化好像理论上没有什么提升,麻烦老师看一下我是哪里想错了吗?谢谢啦~

正在回答 回答被采纳积分+3

1回答

龙虾三少 2022-10-28 17:06:22

我们需要考虑本地线程挂掉 服务重启等各种异常问题 实际生产环境中一秒钟可能就几千单 如果不能正确处理会造成很大的资金和库存问题

0 回复 有任何疑惑可以回复我~
  • 提问者 慕数据5069965 #1
    即便是考虑本地线程挂掉的问题,我们根据挂掉的代码执行位置分为:
    
    redis扣减库存前:方案一前端收到下单失败,不影响数据一致;方案二前端收到下单失败,恢复后stocklog状态为1(unknown),得知本地事务执行中断,mq不发送,不影响数据一致。二者效果一致。
    
    reids扣减库存后:方案一前端收到下单失败,订单若落库会造成无效的订单,mq作为最后一步一定未发送成功。此时mysql数据正确,redis<mysql。
    方案二前端收到下单失败,订单若落库,课程代码也没有回滚,会造成无效订单,stocklog若为1,则效果同方案一(“此时mysql数据正确,redis<mysql”)。stocklog若已置为2,则mq发送消息,redis,mysql数据一致,但都是错误数据(比实际少1)。
    
    可能这里我唯一觉得方案二有价值的点就是线程挂掉订单可以考虑回滚(课程里需要补充这部分逻辑),这样能够一直保证订单和用户感知的一致性。但redis和mysql之间的问题都没有改善,反而还新引入了一种结局(二者都错扣),这样的权衡是否值得呢?
    回复 有任何疑惑可以回复我~ 2022-10-28 18:24:28
问题已解决,确定采纳
还有疑问,暂不采纳
微信客服

购课补贴
联系客服咨询优惠详情

帮助反馈 APP下载

慕课网APP
您的移动学习伙伴

公众号

扫描二维码
关注慕课网微信公众号