Redis实现分布式锁
一、引入的包<dependency><groupId>redis.clients</groupId><artifactId>jedis</artifactId><version>3.2.0</version></dependency>二、加锁,释放锁方法实现public class RedisLock
·
一、引入的包
<dependency>
<groupId>redis.clients</groupId>
<artifactId>jedis</artifactId>
<version>3.2.0</version>
</dependency>
二、加锁,释放锁方法实现
public class RedisLock {
private static JedisPool jedisPool;
// private static Jedis jedis = new JedisPool("192.168.118.128", 3399).getResource();
private static final Logger logger = LoggerFactory.getLogger(RedisLock.class);
static {
// 初始化连接池
JedisPoolConfig jedisPoolConfig = new JedisPoolConfig();
jedisPoolConfig.setMaxTotal(20);
jedisPoolConfig.setMaxIdle(10);
jedisPool = new JedisPool(jedisPoolConfig, "192.168.118.128", 6379);
}
/**
* 循环获得一个锁
*/
public void lock(String key, String value){
for(; ;){ // 通过循环来实现阻塞
if(tryLock(key, value)){
return;
}
try{
TimeUnit.MILLISECONDS.sleep(100);
}catch (InterruptedException e){
e.printStackTrace();
}
}
}
/**
* 尝试加锁
* @param key 设置redis的key
* @param value 通过uuid生成的唯一值,用于判断是不是锁的持有者,因为只有自己才能释放锁
* @return
*/
public boolean tryLock(String key, String value){
Jedis jedis = jedisPool.getResource();
// 设置默认超时时间(nx,px命令的合集)
SetParams setParams = SetParams.setParams().nx().px(4_000);
// Jedis jedis = jedisPool.getResource();
// 设置key和值(加锁操作)
String set = jedis.set(key, value, setParams);
if("OK".equals(set)){
Thread thread = new Thread(() -> {
while (true){
try {
// 开启一个守护线程1s检测一下超时时间
TimeUnit.SECONDS.sleep(1);
}catch (InterruptedException e){
e.printStackTrace();
}
// 获取当前超时时间
Long pttl = jedis.pttl(key);
// 当超时时间小于1/2时,增加超时时间到原来的4s
if(pttl < 2_000){
jedis.expire(key, 4_000);
logger.info("add expire time for key : {}", key);
}
}
}, "expire1");
// 设置为守护线程
thread.setDaemon(true);
thread.start();
return true;
}
return false;
}
/**
* 释放锁
* @param key
* @param value
*/
public void unLock(String key, String value){
Jedis jedis = jedisPool.getResource();
String script =
"if redis.call('get',KEYS[1]) == ARGV[1] then" +
" return redis.call('del',KEYS[1]) " +
"else" +
" return 0 " +
"end";
jedis.eval(script, Collections.singletonList(key), Collections.singletonList(value));
}
}
三、mian方法调用加锁解锁操作
public static void main(String[] args) {
String key = "lock2";
String s = UUID.randomUUID().toString();
RedisLock redisLock = new RedisLock();
// 加锁
redisLock.lock(key, s);
try {
TimeUnit.SECONDS.sleep(3);
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
redisLock.unLock(key, s); // 释放锁
}
}
至此,分布式锁就实现了!
当然了,以上实现还不完善,没有实现可重入,我这里就不实现了,因为已经有了比较成熟的解决方案了,那就是Redisson
Redisson实现分布式锁传送门:https://blog.csdn.net/qq_43037478/article/details/109383965
更多推荐
已为社区贡献1条内容
所有评论(0)