一般来说,把数据库操作和redis操作放放在同一个本地事务是OK的,但是如果把http远程调用和数据库操作放在同一个本地事务中,如果远程调用超时,会导致数据库持锁太久,搞不好就崩溃了,所以最好不要把http远程调用和数据库操作放在同一个本地事务
那么消息队列发送操作呢?是不是处于redis和远程http调用之间?相比redis缓存操作而言要不适合和数据库操作放在本地事务中?消息队列发送操作网络或者消息堆积导致超时的问题比redis等缓存操作要出状况多一些?
另外还有一个问题是,如果服务扣款10元,发送消息到消息队列成功,但是消息中间件给服务发送ack时出问题,导致消息中间件已经成功收到消息,服务却回滚数据库事务,没有扣款,但是消息中间件给消费者发送消息通知扣款成功,立即执行扣款成功后的操作,那就麻烦了。
是的,异步操作放到事务中都不靠谱。
我们曾遇到这么一个情况,在A应用的事务中发送MQ,B应用消费A的MQ并做查库操作,我们遇到了一个bug,就是B应用收到了MQ在做查库操作时,发现数据库中并没有对应的数据,最后发现是A应用的事务未提交,B已经消费A在事务中发出去的MQ了。最后的解决办法就是A中把发送MQ的操作放到事务外面。