jedis setnx实现锁机制

时间:2025-03-22 09:22:52

线上接口有同用户请求的并发问题,所以准备用setnx做一个锁

为什么要用setnx:因为 Redis Setnx(SET if Not eXists) 命令是在指定的 key 不存在时,为 key 设置指定的值,所以setnx是redis的一个原子性命令

实现思路:根据用户信息生成一个key,放缓存待 接口执行完毕之后,删除该缓存,下次同用户请求进来,如果未执行完毕则缓存还存在,放缓存失败则返回对应提示信息,接口停止继续执行

上代码:

    @Autowired(required = false)
    private Pool<Jedis> poolJedis;


   /**
     * 添加锁 防并发 此方法添加锁未设置过期时间,需手动释放
     *
     * @param key key
     * @param seconds 缓存过期时间
     * @return boolean
     */
    public boolean tryLock(String key,int seconds) {
        if ((poolJedis)) {
            return false;
        }
        try (Jedis jedisCluster = ()) {
            // 在指定的 key 不存在时,为 key 设置指定的值。
            // 根据以下第三个nxxx参数,把key、value set到redis中
            // NX : not exists, 只有key 不存在时才把key value set 到redis
            // XX : is  exists, 只有key 存在时才把key value set 到redis
            // 第四个expx参数有两个值可选 :
            // EX : seconds 秒
            // PX :  milliseconds 毫秒
            String nx = (key, "value", "NX", "EX", seconds);
            if ((nx) && "OK".equals(nx)) {
                return true;
            }
        } catch (Exception e) {
            ("addLock error:", e);
        }
        return false;
    }



   /**
     * 释放锁
     *
     * @param key key
     */
    public void clearLock(String key) {
        Jedis jedisCluster = null;
        try {
            jedisCluster = ();
            Long a = jedisCluster .del(key);
        } catch (Exception e) {
            ("", e);
            //线程休眠1秒
            try {
                (1000);
                removeLock(key);
            } catch (InterruptedException e1) {
                ("removeLock error:", e1);
                ().interrupt();
            } finally {
                if (jedisCluster != null) {
                    jedisCluster .close();
                }
            }
        }
    }