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



浙公网安备 33010602011771号