0

一般来说,把数据库操作和redis操作放放在同一个本地事务是OK的,但是如果把http远程调用和数据库操作放在同一个本地事务中,如果远程调用超时,会导致数据库持锁太久,搞不好就崩溃了,所以最好不要把http远程调用和数据库操作放在同一个本地事务

那么消息队列发送操作呢?是不是处于redis和远程http调用之间?相比redis缓存操作而言要不适合和数据库操作放在本地事务中?消息队列发送操作网络或者消息堆积导致超时的问题比redis等缓存操作要出状况多一些?

另外还有一个问题是,如果服务扣款10元,发送消息到消息队列成功,但是消息中间件给服务发送ack时出问题,导致消息中间件已经成功收到消息,服务却回滚数据库事务,没有扣款,但是消息中间件给消费者发送消息通知扣款成功,立即执行扣款成功后的操作,那就麻烦了。

esolve 890
12月4日提问
2 个回答
0

是的,异步操作放到事务中都不靠谱。
我们曾遇到这么一个情况,在A应用的事务中发送MQ,B应用消费A的MQ并做查库操作,我们遇到了一个bug,就是B应用收到了MQ在做查库操作时,发现数据库中并没有对应的数据,最后发现是A应用的事务未提交,B已经消费A在事务中发出去的MQ了。最后的解决办法就是A中把发送MQ的操作放到事务外面。

0

现在有些消息队列是支持发送事务型消息的。这些消息队列利用类似两阶段提交协议,先发送一条half消息,然后根据事务的提交或回滚发出提交或回滚消息。因为消息可能丢失,所以发送消息方需要提供回查能力帮助broker判断事务是成功还是失败还是还没执行完毕。非事务型消息场景不要把消息方在本地事务中,但是如果是事务型消息的场景,可以使用支持事务型消息的消息中间件来玩。

像这种资金相关的场景,就应该使用事务型消息保证最终一致性

撰写答案

推广链接