yllllllllllll 2023-03-15 00:55 采纳率: 0%
浏览 47

关于springboot使用redisTemplate实现分布式锁的问题。

关于springboot使用redisTemplate实现分布式锁的问题。

img

img

代码如上,通过redisTemplate的api里的setIfAbsent给redis加锁,然后用delete去解锁。在buy方法中先加锁然后阻塞十秒模拟业务流程,业务流程以后再解锁。然后打开浏览器,开俩个窗口,模拟俩个线程去调用buy(俩个线程参数key是一样)。理想中的过程是,第一个线程调用的时候,加锁以后然后阻塞的十秒之内,再用第二个窗口模拟第二个线程去调用,然后setIfAbsent返回false,buy方法直接返回lock来表示本次调用失效。想实现这么一个接口幂等性校验的场景。
但是这个场景没有实现,发现了一个问题,在第一个线程调用setIfAbsent以后,然后再阻塞的10秒之内, 第二个线程再用相同的key去调用setIfAbsent,会一直等待第一个线程完全执行完以后,setIfAbsent才会返回。但是再第一个线程执行完以后,已经将该key进行了delete,所以第二个线程调用setIfAbsent的结果也是true,俩个线程都返回了buy,导致无法实现接口幂等性校验的场景。
个人对redis了解的比较少,以前都是用来存放用户的token用,以我个人的直觉猜测可能是redis的事务问题,在第一个线程执行setIfAbsent后,阻塞的十秒时间内,redis一直是事务未提交的状态,然后第二个线程再接着去调用setIfAbsent发现该key未提交事务,会一直等待第一个事务提交完事务以后,再进行setnx操作。但是这个也只是本人对关系型数据库的了解作出的猜测,对非关系行数据库确实了解了解较少,所有在此希望CSDN各位可以为指教一下出现这个问题的原因和解决方案。

  • 写回答

2条回答 默认 最新

  • 憧憬blog 2023-03-15 03:16
    关注

    您的猜测是正确的。redis的setIfAbsent操作是原子操作,但是如果多个操作需要同时执行才能完成一个完整的事务,那么就需要用到redis的事务管理机制——multi/exec。在您的代码中,没有使用multi/exec将setIfAbsent和delete操作包含在一个事务中,导致第二个线程在等待第一个线程的事务提交后才能获取到锁,然而第一个线程已经将锁释放了,导致第二个线程仍然获取到了锁,并对业务进行了处理。

    解决方案是将setIfAbsent和delete操作包含在同一个事务中执行,这样就可以保证原子性,避免出现锁被重复获取的情况。代码示例如下:

    public void buy(String key) {
        String lock = "lock:" + key;
        if (redisTemplate.opsForValue().setIfAbsent(lock, "value")) {
            redisTemplate.expire(lock, 10, TimeUnit.SECONDS);
            try {
                Thread.sleep(10000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            // 业务处理代码
        } else {
            // 获取锁失败,处理重复请求的逻辑
            redisTemplate.watch(lock);
            redisTemplate.multi(); // 开启事务
            redisTemplate.delete(lock);
            redisTemplate.exec(); // 提交事务
        }
    }
    
    评论

报告相同问题?

问题事件

  • 创建了问题 3月15日

悬赏问题

  • ¥15 券商软件上市公司信息获取问题
  • ¥100 ensp启动设备蓝屏,代码clock_watchdog_timeout
  • ¥15 Android studio AVD启动不了
  • ¥15 陆空双模式无人机怎么做
  • ¥15 想咨询点问题,与算法转换,负荷预测,数字孪生有关
  • ¥15 C#中的编译平台的区别影响
  • ¥15 软件供应链安全是跟可靠性有关还是跟安全性有关?
  • ¥15 电脑蓝屏logfilessrtsrttrail问题
  • ¥20 关于wordpress建站遇到的问题!(语言-php)(相关搜索:云服务器)
  • ¥15 【求职】怎么找到一个周围人素质都很高不会欺负他人,并且未来月薪能够达到一万以上(技术岗)的工作?希望可以收到写有具体,可靠,已经实践过了的路径的回答?