redis分布式锁

基于单点Redis的分布式锁

获取锁

SET resource_name my_random_value NX PX 30000

释放锁

if redis.call("get",KEYS[1]) == ARGV[1] then
    return redis.call("del",KEYS[1])
else
    return 0
end

这里的KEYS[1],ARGV[1]就是前面创建锁时的key和value

如果没有设置过期时间当一个客户端获取锁成功之后,假如它崩溃了,或者由于发生了网络分割导致无法与redis通信了,那么它就会一直持有这个锁,而其他客户端就永远无法获取到锁了  

如果将这个命令实现为两个redis命令

SETNX resource_name my_random_value
EXPIRE resource_name 30

如果执行完第一个命令后崩溃了,那么就没办法再执行第二个命令了,导致一直持有这个锁

这个随机字符串可以保证客户端释放的锁是属于自已的,假如锁的值是一个固定值,那么就有可能发生如下情况

锁释放包含三步操作:GET,判断,删除 ,这三步必须是原子操作,否则就会发生执行序列的问题    


基于单点redis节点的分布式锁就介绍完毕了,但是却有一个很致命的问题就是单点redis宕机,那么所有客户端就无法来获取锁了,虽然redis有主从复制,但是确实异步的,这可能在failover过程中丧失锁的安全性

于是客户端1和2都持有了同一个资源的锁

分布式锁ReadLock

由于基于单点Redis节点分布式锁在failover的时候会产生解决补了的安全性问题,因为Redlock的产生就是为了解决这个问题,它基于N个完全独立的Redis节点

运行Redlock算法的客户端一次执行下面的各个步骤,来完成获取锁的操作


redlock很好的解决了由于单点redis分布式锁的failover问题,看似已经完美但是也有些问题,当节点发生崩溃重启,还是会对锁可能会产生影响,具体和redis的数据持久化程度有关

假设有五个redis节点:A、B、C、D、E。获取锁时发生了如下的时间

客户端1和客户端2同时获取到了锁,导致了访问同一资源