public class RedisLock {
private static final Long RELEASE_SUCCESS = 1L;
private static final String LOCK_SUCCESS = "OK";
//NX:NX-key不存在时进行保存,XX:XX-key存在时才进行保存
private static final String SET_IF_NOT_EXIST = "NX";
//过期时间单位 (EX,PX),EX-秒,PX-毫秒
private static final String SET_WITH_EXPIRE_TIME = "EX";
private static final String RELEASE_LOCK_SCRIPT = "if redis.call('get', KEYS[1]) == ARGV[1] then return redis.call('del', KEYS[1]) else return 0 end";
private static final StringRedisTemplate REDIS_TEMPLATE;
static {
REDIS_TEMPLATE = ContextUtils.getBean(StringRedisTemplate.class);
}
/**
* 该加锁方法仅针对单实例 Redis 可实现分布式加锁
* 对于 Redis 集群则无法使用
*
* 支持重复,线程安全
*
* @param lockKey 加锁键
* @param clientId 加锁客户端唯一标识(采用UUID)
* @param seconds 锁过期时间
* @return
*/
public static Boolean tryLock(String lockKey, String clientId, long seconds) {
return REDIS_TEMPLATE.execute((RedisCallback<Boolean>) redisConnection -> {
Jedis jedis = (Jedis) redisConnection.getNativeConnection();
String result = jedis.set(lockKey, clientId, SET_IF_NOT_EXIST, SET_WITH_EXPIRE_TIME, seconds);
if (LOCK_SUCCESS.equals(result)) {
return Boolean.TRUE;
}
return Boolean.FALSE;
});
}
/**
* 与 tryLock 相对应,用作释放锁
*
* @param lockKey
* @param clientId
* @return
*/
public static Boolean releaseLock(String lockKey, String clientId) {
return REDIS_TEMPLATE.execute((RedisCallback<Boolean>) redisConnection -> {
Jedis jedis = (Jedis) redisConnection.getNativeConnection();
Object result = jedis.eval(RELEASE_LOCK_SCRIPT, Collections.singletonList(lockKey),
Collections.singletonList(clientId));
if (RELEASE_SUCCESS.equals(result)) {
return Boolean.TRUE;
}
return Boolean.FALSE;
});
}
}
StringRedisTemplate实现分布式锁
最新推荐文章于 2025-03-22 22:51:03 发布