高并发下乐观锁实现

目前有业务并发更新某业务表,比如用户账户表,可考虑利用数据库乐观锁的办法解决。

1、表设计

     需要在表中新增version字段,可定义为bigint类型,初始值可设置为0

2、更新语句mybatis的实现

<update id="updateConsumeStarWithLook">
        update sys_user_consume_star 
            set current_consume_star_amount = #{currentConsumeStarAmount},
                update_time = #{updateTime, jdbcType=TIMESTAMP},
                version = version + 1
            where id = #{id} and version = #{version}
    </update>

3、业务逻辑层,实现思路:可定义一个更新方法,先查询出当前记录,根据业务进行调用乐观锁实现的updateConsumeStarWithLook,如果更新成功,即该返回值为1时,表示更新成功,当返回值为0时,表示未成功更新,可再次递归调用该更新方法。

private void updateUserConsumeStarWithLook(String userId,Long starAmount) {
        
        Wrapper<SysUserConsumeStar> wrapper = new QueryWrapper<SysUserConsumeStar>()
                .eq("user_id", userId);
        
        SysUserConsumeStar sysUserConsumeStar = sysUserConsumeStarService.getOne(wrapper);
        
        Long oldStartAmount = sysUserConsumeStar.getCurrentConsumeStarAmount();
                 
        Long newStartAmount = oldStartAmount + starAmount;

        sysUserConsumeStar.setCurrentConsumeStarAmount(newStartAmount).setUpdateTime(LocalDateTime.now());
                
        Integer result =  sysUserConsumeStarService.updateConsumeStarWithLook(sysUserConsumeStar);
        
        //如果更新失败则继续尝试直到成功为止
        if(result == 0) {
            
            updateUserConsumeStarWithLook(userId,flowType,starAmount);
            
        }
    }

4、在具体调用上述方法的方法上如果需要加上事务,则需要将事务的隔离级别定义为读已提交,不然在查询的时候会出现脏读,更新无法成功,导致死循环

@Transactional(rollbackFor = Exception.class,isolation=Isolation.READ_COMMITTED,propagation=Propagation.REQUIRED)

 5、测试,可使用JMater,相关教程可参考:https://blog.youkuaiyun.com/u010481688/article/details/81032259

转载于:https://www.cnblogs.com/conswin/p/10724343.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值