package ...;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.dao.DataAccessException;
import org.springframework.data.redis.connection.RedisConnection;
import org.springframework.data.redis.core.RedisCallback;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Component;
import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisCluster;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.TimeUnit;
/**
* Created by LiuZengqiang on 2018/10/15.
*/
@Component
public class RedisLock {
@Autowired
private StringRedisTemplate stringRedisTemplate;
@Autowired
private RedisTemplate redisTemplate;
/**
* 获取锁
*
* @param lockKey Key
* @param lockValue Value
* @param expireTime 单位分钟
* @return
*/
public boolean tryGetDistributedLock(String lockKey, String lockValue, long expireTime) {
boolean result = stringRedisTemplate.opsForValue().setIfAbsent(lockKey, lockValue);
if (result) {
stringRedisTemplate.expire(lockKey, expireTime, TimeUnit.MINUTES);
return true;
} else if (stringRedisTemplate.getExpire(lockKey) == -1L) {
stringRedisTemplate.expire(lockKey, expireTime, TimeUnit.MINUTES);
}
return false;
}
/**
* 释放锁
*
* @param lockKey Key
* @param lockValue Value
* @return
*/
public boolean releaseDistributedLock(String lockKey, String lockValue) {
if (lockValue.equals(stringRedisTemplate.opsForValue().get(lockKey))) {
stringRedisTemplate.delete(lockKey);
return true;
}
return false;
}
/**
* 获取锁 Lua
*
* @param lockKey
* @param lockValue
* @param expireTime
* @return
*/
public boolean tryGetDistributedLockByLua(String lockKey, String lockValue, long expireTime) {
String LUA = "if redis.call('setnx',KEYS[1],ARGV[1] )==1 then return redis.call('expire',KEYS[1], ARGV[2]) end if redis.call('ttl',KEYS[1]) == -1 then redis.call('expire',KEYS[1], ARGV[2]) end return 0";
List<String> keys = new ArrayList<>();
keys.add(lockKey);
List<String> args = new ArrayList<>();
args.add(lockValue);
args.add(expireTime * 60 + "");
Long result = (Long) redisTemplate.execute(new RedisCallbackImpl(LUA, keys, args));
if (1 == result) {
return true;
}
return false;
}
/**
* 释放锁 Lua
*
* @param lockKey
* @param lockValue
* @return
*/
public boolean releaseDistributedLockByLua(String lockKey, String lockValue) {
String LUA = "if redis.call('get',KEYS[1]) == ARGV[1] then return redis.call('del',KEYS[1]) else return 0 end";
List<String> keys = new ArrayList<>();
keys.add(lockKey);
List<String> args = new ArrayList<>();
args.add(lockValue);
Long result = (Long) redisTemplate.execute(new RedisCallbackImpl(LUA, keys, args));
if (1 == result) {
return true;
}
return false;
}
private class RedisCallbackImpl implements RedisCallback {
private String lua;
private List<String> keys;
private List<String> args;
public RedisCallbackImpl(String lua, List<String> keys, List<String> args) {
this.lua = lua;
this.keys = keys;
this.args = args;
}
@Override
public Long doInRedis(RedisConnection connection) throws DataAccessException {
Object nativeConnection = connection.getNativeConnection();
if (nativeConnection instanceof JedisCluster) {
return (Long) ((JedisCluster) nativeConnection).eval(lua, keys, args);
} else if (nativeConnection instanceof Jedis) {
return (Long) ((Jedis) nativeConnection).eval(lua, keys, args);
}
return null;
}
}
}
暂无评论