如何确保事务提交后才执行异步操作

参考博客TransactionSynchronizationManager和TransactionSynchronizationAdapter

场景

业务流程背景:
对于“法律法规-法规库-标签管理”列表中的某一条数据,操作完标注和解析按钮后,我会更新该条数据的状态字段并向redis写入一条消息。web端开发从redis取消息会先判断一下该数据的状态字段看是否应该写入es,如果不应该,会告警。

问题原因:
由于改代码涉及多张表操作,故使用声明式事务,并在代码末尾异步往redis里写入消息。如果此时redis里面没消息,并且我这段代码事务提交耗时相当严重,会导致数据的状态我这边还未改变,然后web端开发取到消息他发现状态字段未发生改变,从而发出告警并且没有写入es。
在这里插入图片描述

假代码如下:
在这里插入图片描述
在这里插入图片描述

一种解决方法是:在异步的方法中手动延时操作,尽可能保证事务的提交。但是此时间并不好评估,非最优解。

二是:如果保证事务提交完成后,再去发送异步消息呢?

    /**
     * 新增保存用户信息
     * 
     * @param user 用户信息
     * @return 结果
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public int insertUser(SysUser user)
    {
        // 新增用户信息
        int rows = userMapper.insertUser(user);
        // 新增用户岗位关联
        insertUserPost(user);
        // 新增用户与角色管理
        insertUserRole(user);
        //如果有事务,则事务提交之后在执行
        if (TransactionSynchronizationManager.isActualTransactionActive()) {
            TransactionSynchronizationManager.registerSynchronization(new TransactionSynchronizationAdapter() {
                @Override
                public void afterCommit() {
                    // todo 异步任务,如http请求,mq发送等
                    taskService.notifyEs("sys_user", "insert", user.getUserId().toString());
                }
            });
        } else {
            //没有事务,直接执行
            taskService.notifyEs("sys_user", "insert", user.getUserId().toString());
        }
        try {
            //模拟事务提交耗时
            Thread.sleep(10000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        return rows;
    }
  • 2
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值