redis分布式锁关键点与实现

1、使用setnx设置key。

2、保证自己删线程的时候不去删除别人的。

3、设置线程key的作用时间,不会永久。

4、系统启动时可以先清空这个redis key值。

那么如何实现呢?

见下面代码:

String script = "if redis.call('get', KEYS[1]) == ARGV[1] then return redis.call('del', KEYS[1]) else return 0 end";
Long result = jedis.eval(script, Collections.singletonList("lock_key"), Collections.singletonList("thread_identifier"));
if (result == 1) {
    System.out.println("锁释放成功");
} else {
    System.out.println("锁释放失败(锁不属于当前线程)");
}

设置redis值的时候是设置的uuid,取值的时候拿系统里的uuid取和redis里存的去判断,如果相等则删除,如果不相等就什么都不做,这几个操作是原子的,使用lua脚本去执行。

Lua脚本解决多条命令原子性问题
Redis提供了Lua脚本功能,在一个脚本中编写多条Redis命令,确保多条命令执行时的原子性

 

if (redis.call('exists', KEYS[1]) == 0) then redis.call('hset', KEYS[1], ARGV[2], 1); redis.call('pexpire', KEYS[1], ARGV[1]); return nil; end;
if (redis.call('hexists', KEYS[1], ARGV[2]) == 1) then redis.call('hincrby', KEYS[1], ARGV[2], 1); redis.call('pexpire', KEYS[1], ARGV[1]); return nil; end;
return redis.call('pttl', KEYS[1]);

return this.commandExecutor.evalWriteAsync(this.getName(), LongCodec.INSTANCE, RedisCommands.EVAL_BOOLEAN, "if (redis.call('exists', KEYS[1]) == 0) then redis.call('publish', KEYS[2], ARGV[1]); return 1; end;if (redis.call('hexists', KEYS[1], ARGV[3]) == 0) then return nil;end; local counter = redis.call('hincrby', KEYS[1], ARGV[3], -1); if (counter > 0) then redis.call('pexpire', KEYS[1], ARGV[2]); return 0; else redis.call('del', KEYS[1]); redis.call('publish', KEYS[2], ARGV[1]); return 1; end; return nil;", Arrays.asList(this.getName(), this.getChannelName()), new Object[]{LockPubSub.unlockMessage, this.internalLockLeaseTime, this.getLockName(threadId)});


原文链接:https://blog.csdn.net/qq_45637260/article/details/126099398

 

 

分布式锁主从同步失败,那么查询的时候从库是能查到数据的

 

经典文章:https://developer.aliyun.com/article/1318463

 

 

 

 

posted on 2025-05-08 18:30  Hi Martin  阅读(19)  评论(0)    收藏  举报