transaction事务和rocketMq发消息踩坑记

335 阅读1分钟

问题描述

数据推送只有部分推送成功,推送失败的报查询不存在的异常,经排查是没保存数据库成功就去查询了,因为发MQ消息是异步的。推送的逻辑是在审核成功之后,审核里面操作比较多,开启了事务,有:一系列的数据库操作,其中一个操作异常就全部回滚。使用的是Transaction实现事务。

方案一:

具体实现代码,通过spring 注解Transactional实现事务,使用TransactionSynchronizationManger注册一个异步afterCommit事件实现提交事务后再发消息。

classA implements InterfaceA{
    Result<String> methodA(){
       
        boolean result = methodAWrapper();
                TransactionSynchronizationManager.registerSynchronization(new TransactionSynchronization() {
            @Override
            public void afterCommit() {
                //审核成功无异常才发MQ消息
                    if (result) {
                        sendAddMqMessage();
                    }
            }
        });
        
        return Result.success("审核成功");
   }
}


缺点:把异常信息直接抛给前端了,一大串英文错误很不友好,虽然自定义异常然后可以全局捕获异常,但是我们只希望返回给前端的信息就只是“审核成功”或”审核失败“,有些异常不是自定义异常时就是默认处理了。举个栗子:feign调服务,服务不可用一般都会主动捕获这个连接异常,若没设置feign失败策略,就把不友好异常给前端了。

方案二:

classA implements InterfaceA{
    Result<String> methodA(){
        try{
            ((InterfaceA)AopContext.currentProxy()).methodB();
        } catch(Exception e)
        {
            log.error("异常",e);
            return Result.failed("审核失败");
        }
        return Result.success("审核成功");
   }
       
    @Override
    @Transactional(rollbackFor = Exception.class, propagation = Propagation.REQUIRED)
    methodB(){
        //操作数据库
   }
}
​

优点:既可以使用注解Transactional实现事务,又可以捕获异常;

缺点:多定义了一个方法.

期间顺便学习了Transactional的7种传播机制,决定使用默认的required就可以。