Redis分布式锁

Redis分布式锁_第1张图片

做一个redis分布式锁需要他满足哪些条件
1,保证锁的唯一性(redis的setnx来保证锁的唯一性)
2,保证在某个请求出现错误的情况下锁能够正常释放(首先我们想到的是使用try->finally{释放掉锁}),还要保证整个流程是原子的
3,当我们的程序故障,没有走到finally的时候,我们要保证锁的释放,这时候设置过期时间
4,当前操作耗时过长,导致锁已释放但是程序并没有走完,这时候我们需要给锁的过期时间续期
5,要满足这些条件,我们可以引用redssion来很好的实现我们的需求从而做到分布式锁
6,
a、加锁机制
线程去获取锁,获取成功: 执行lua脚本,保存数据到redis数据库。
线程去获取锁,获取失败: 一直通过while循环尝试获取锁,获取成功后,执行lua脚本,保存数据到redis数据库。
b、watch dog自动延期机制
在一个分布式环境下,假如一个线程获得锁后,突然服务器宕机了,那么这个时候在一定时间后这个锁会自动释放,你也可以设置锁的有效时间(不设置默认30秒),这样的目的主要是防止死锁的发生
只要客户端1一旦加锁成功,就会启动一个watch dog看门狗,他是一个后台线程,会每隔10秒检查一下,如果客户端1还持有锁key,那么就会不断的延长锁key的生存时间。

lua脚本

-- 若锁不存在:则直接广播解锁消息,并返回1
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; 
-- 若锁存在,且唯一标识匹配:则先将锁重入计数减1
local counter = redis.call('hincrby', KEYS[1], ARGV[3], -1); 
if (counter > 0) then 
    -- 锁重入计数减1后还大于0:表明当前线程持有的锁还有重入,不能进行锁删除操作,但可以友好地帮忙设置下过期时期
    redis.call('pexpire', KEYS[1], ARGV[2]); 
    return 0; 
else 
    -- 锁重入计数已为0:间接表明锁已释放了。直接删除掉锁,并广播解锁消息,去唤醒那些争抢过锁但还处于阻塞中的线程
    redis.call('del', KEYS[1]); 
    redis.call('publish', KEYS[2], ARGV[1]); 
    return 1;
end;

你可能感兴趣的:(图灵学习,#,四:分布式框架专题,redis,分布式,数据库)