Author:赵志乾
Date:2020-08-14
Declaration:All Right Reserved!!!
踩坑:
场景:数据库事务执行完,需要执行异步任务;例如向Redis发布消息;
做法:事务的最后一步执行消息发布;代码如下:
@Transactional(rollbackFor = Exception.class)
public void doMyTransaction(Object param) {
// step1: 执行事务操作
// step2: 发布Redis消息
}
现象:Redis订阅端收到消息后,立刻读库,拿到的是修改前的数据(事务隔离级别是提交读);
解决方案:
上述问题是由于消息发布放置在事务中导致的。Redis消息订阅端收到消息进行读库时,事务还没有完成提交。其本质在于对Spring事务工作原理的认知不足。Spring声明式事务是基于Aop实现的,提交操作发生在方法正常返回后,也就是在包裹该方法的切面里完成的。
解决方案也比较简单,就是讲发布消息的操作移到doMyTransaction之外,确保消息发布时,数据库变更已提交。