基于redis实现分布式锁
背景
一套代码部署在四个服务器上,代码逻辑是:检查当前表的总数据条数,满足一定条件后切换到下一个分表
四个同时都去切换表 + 1 的操作是不可以的,他们要先从 redis 获取一把锁,没有获取到锁的就直接退出,等待下一次定时任务的调度。拿到了锁的就去执行切换当前分表的操作
实现
获取锁 和 释放锁 的关键代码如下所示:
/**
* Set the string value as value of the key. The string can't be longer than 1073741824 bytes (1
* GB).
* @param key
* @param value
* @param nxxx NX|XX, NX -- Only set the key if it does not already exist. XX -- Only set the key
* if it already exist.
* @param expx EX|PX, expire time units: EX = seconds; PX = milliseconds
* @param time expire time in the units of <code>expx</code>
* @return Status code reply
* @auther daleyzou
*/
public boolean set(String key, String value, String nxxx, String expx,
long time) {
Jedis jedis = jedisPool.getResource();
try {
String result = jedis.set(key, value, nxxx, expx, time);
if (!StringUtils.isNullOrEmpty(result) && "OK".equals(result)){
return true;
}else {
return false;
}
} catch (Exception e) {
dealWithJedisException(e);
} finally {
closeJedis(jedis);
}
return false;
}
/***
* @Description: 解锁时比较值是否相等
* @date: 22:33 2019/7/22
* @param: key
* @param: request value
* @return: boolean
*/
public boolean unlock(String key,String request){
Jedis jedis = jedisPool.getResource();
try {
String script = "if redis.call('get', KEYS[1]) == ARGV[1] then return redis.call('del', KEYS[1]) else return 0 end";
Object result = jedis.eval(script, Collections.singletonList(key), Collections.singletonList(request));
Long UNLOCK_SUCCESS = 1L;
if (UNLOCK_SUCCESS.equals(result)){
return true;
}else {
return false;
}
} catch (Exception e) {
dealWithJedisException(e);
} finally {
closeJedis(jedis);
}
return false;
}
调用
private static final String SET_IF_NOT_EXIST = "NX";
private static final String SET_WITH_EXPIRE_TIME = "EX";
if (myJedisService.set(refreshMaxId, value, SET_IF_NOT_EXIST, SET_WITH_EXPIRE_TIME, expireTime)){
// 执行并发的相关操作
。。。
myJedisService.unlock(refreshMaxId, value);
return;
}else {
return;
}
参考
参考链接:https://crossoverjie.top/2018/03/29/distributed-lock/distributed-lock-redis/