这里涉及了两个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);
}
}
本文详细解析了如何使用Redis的String类型set方法实现分布式锁,包括set的用法、nx和px选项,以及在业务场景中的应用,如lockDemo方法和自定义JedisLockService。
328

被折叠的 条评论
为什么被折叠?



