使用jedis操作redis构建分布式锁操作

本文详细解析了如何使用Redis的String类型set方法实现分布式锁,包括set的用法、nx和px选项,以及在业务场景中的应用,如lockDemo方法和自定义JedisLockService。

这里涉及了两个redis对于String类型的操作方法

1、String   set(String key, String value, String nxxx, String expx, int time) 
2、String   set(String key, String value, String nxxx, String expx, long time)

功能都是一样的,将string类型的value 放到key的value上,返回值都是 String。

1、把key、value set到redis中,隐含覆盖,默认的ttl是-1(永不过期)

2、根据第三个参数,把key、value set到redis中
nx : not exists, 只有key 不存在时才把key value set 到redis

(还有一个 xx : is exists ,只有 key 存在是,才把key value set 到redis)

3、第四个参数,只是多加了个过期时间
expx参数有两个值可选 :
ex : seconds 秒
px : milliseconds 毫秒

使用其他值,抛出 异常 : redis.clients.jedis.exceptions.JedisDataException : ERR syntax error

4、第五个参数可以是long,也可以是int,意思都是设置超时时间。
 

返回值String,如果写入成功是“OK”,写入失败返回空

构建分布式锁

业务层代码

public void lockDemo(Long id){
    String key = RedisKey.use_lock.getKey(id.toString());
    // 获取分布式锁
    String lockVal = jedisLockService.lock(key, 10 * 1000, 5 * 1000);
    if (BlankUtil.isBlank(lockVal)) {
        logger.error("获取分布式锁失败,uid:{}", uid);
        throw new ApiException("操作频繁,请稍后重试");
    }

    try {
            //=======执行业务逻辑========
    }finally {
            // 释放锁, 即删除该key
            jedisLockService.unlock(key, lockVal);
     }

}

jedisLockServcie 自定义封装jedis操作redis的业务方法

// JedsiLockService 通过jedis进行redis操作的封装工具类
public String lock(String lockKey, int waitTime, int timeout) {
        Jedis jedis = null;
        try {
            jedis = writeJedisPoolManager.getJedis();
            return lock(jedis, lockKey, waitTime, timeout);
        } catch (Exception e) {
            logger.error("lock error", e);
        } finally {
            if (jedis != null) {
                jedis.close();
            }
        }
        return null;
    }

// 通过自旋方式尝试获取锁, 如果自旋期间获取不到锁则返回null
public String lock(Jedis jedis, String lockKey, int waitTime, int timeout) {
        int retryTime = waitTime;
        try {
            long lockValue = 0;
            while (retryTime > 0) {
                lockValue = System.nanoTime();
                if ("OK"
                        .equalsIgnoreCase(jedis.set(lockKey, String.valueOf(lockValue), "NX", "PX", timeout))) {
                    return lockValue + "";
                }
                retryTime -= 100;
                Thread.sleep(100);
            }
        } catch (Exception e) {
            logger.error(
                    "lock error, lockKey:" + lockKey + ", waitTime:" + waitTime + ", timeout:" + timeout, e);
        }
        return null;
    }

// 解锁=> 即加锁后执行完业务流程, 进行锁的释放操作
public void unlock(String lockKey, String lockVal) {
        Jedis jedis = null;
        try {
            jedis = writeJedisPoolManager.getJedis();
            unlock(jedis, lockKey, lockVal);
        } catch (Exception e) {
            logger.error("unlock error, lockKey:" + lockKey + ", lockVal:" + lockVal, e);
        } finally {
            if (jedis != null) {
                jedis.close();
            }
        }
    }

    public void unlock(Jedis jedis, String lockKey, String lockVal) {
        String currLockVal = jedis.get(lockKey);
        if (currLockVal != null && currLockVal.equals(lockVal)) {
            jedis.del(lockKey);
        }
    }

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值