【解决案例】分布式锁Redission加锁无效

案例背景
项目需求是生成一段自增的编号,由于编号涵盖不同字符,所以需要编写生成编号的逻辑

1. 问题初解决,加锁

在有该需求前提下,编写如下伪代码

@Transaction(rollbackFor = Exception.class)
    public void test() {
        //获取当前数据库编号信息并做一定处理得到生成的编号
        //省去业务操作
        String baseNum = "xxxx03";
        
        //新生成编号保存至数据库
        baseService.save(baseNum);
        ..
        ..
        ..
        //业务代码
    }

在上面情况下发现有编号重复现象,于是尝试加锁解决,因为是多服务,使用分布式锁Redission,伪代码如下

	@Transaction(rollbackFor = Exception.class)
    public void test() {
        RLock lock = redissionClient.getLock("lock");
        boolean flag = lock.tryLock(5, 10, TimeUnit.SECONDS);
        if (flag) {
            try {
                //获取当前数据库编号信息并做一定处理得到生成的编号
                //省去业务操作
                String baseNum = "xxxx03";

                //新生成编号保存至数据库
                baseService.save(baseNum);
            } finally {
                lock.unlock();
            }
        }
        ..
        ..
        ..
        //业务代码
    }

2. Redission失效?

在使用上面方案后,发现还是会有重复编号出现,难道是Redission失效了?

这点应该不可能,于是开始对代码再次分析,整体代码只锁住了关于编号操作,是其他的模块导致的么?

于是试着将整块代码锁住,重复编号就没再出现。

回过头来,再次对代码分析,发现导致编号重复的是@Transaction这个注解,这段代码整体是一个事务,而事务有ACID四大特性,事务彼此隔离,即不可见,导致编号的修改对于其他事务是不可见的,如图所示,整体可以分成两部分
在这里插入图片描述
在这段代码中,由于事务不可见的特性,在当前事务完成过程中其他线程读取到数据库的值其实还是未操作的数据,从而导致数据重复。

于是将编号生成单独拆分出一个事务进行处理,问题到此结束。

重新温习事务四大特性
在这里插入图片描述

参与评论 您还未登录,请先 登录 后发表或查看评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
©️2022 CSDN 皮肤主题:技术工厂 设计师:CSDN官方博客 返回首页

打赏作者

承与

你的鼓励将是我创作的最大动力

¥2 ¥4 ¥6 ¥10 ¥20
输入1-500的整数
余额支付 (余额:-- )
扫码支付
扫码支付:¥2
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值