一.怎样使用redis实现分布式锁?
最普通的实现方式,如果就是在redis里创建一个key算加锁
SET my:lock 随机值 NX PX 30000,这个命令就ok,这个的NX的意思就是只有key不存在的时候才会设置成功,PX 30000的意思是30秒后锁自动释放。别人创建的时候如果发现已经有了就不能加锁了。
释放锁就是删除key,但是一般可以用lua脚本删除,判断value一样才删除:
if redis.call("get",KEYS[1]) == ARGV[1] then
return redis.call("del",KEYS[1])
else
return 0
end
常见得问题
-
假如抢到锁得实例运行一段时候后挂了? 那么这个时候可能就发生死锁了,所以需要加上一个过期时间(timeout) -
当c1抢到锁,那么此时c2需要做什么? 需要不断得询问,就是通过IO发送setnx指令,那么这个时候如果同时抢得线程很多,其实是比较浪费cpu得,这个时候可以有一个思路:就是使用redis发布订阅+阻塞队列方式,当然这里逻辑可能比较复杂,个人觉得其实实现和reentrantlock内部实现大致一样. -
如果c1拿到了锁,但是执行时间超过了timeout? 如果超过timeout,但是还没有执行完,这个时候其他线程又抢到了锁,就有问题,所以这个时候需要再开辟一个线程,去检测并增加这个过期时间. -
为什么要给锁加标识? 其实是增加了对锁得精准操作,防止误删,确保删除得锁一定是自己加得,确保这个唯一性,一般使用UUID. -
redis挂了怎么处理? 这个首先要说一下redis得几种模式,单机模式就先不说了,redis主要有主从模式和cluster模式,在实际使用过程中会两者结合使用,即主要使用cluster模式,对于每个节点又使用主从复制,而在主从复制中,redis是保证AP得,所以可能会有数据一致性得问题,就是假如某个节点挂了,它得备份节点可能刚好又没有对应得key,这个时候就又出现问题,所以出现了redlock算法.
redlock
首先说明redlock并不是在redis中的,而是在客户端得一种算法.
其本质核心是: ? ? ?给定多个redis独立节点,假如有三个,客户端在争抢锁得时候,同时给这三个节点发送请求,当在这些节点中获得锁得数量超过半数时,就可以真正得获取这把锁,那么此时如果某个节点挂点,这个分布锁还在,就不会受到影响.
|