问:如何通过Redis 实现分布式锁?
首先要明确分布式锁需要解决的问题:
- 互斥性(任意时刻只能有一个客户端获取锁)
- 安全性(锁只能由持有该锁的客户端删除,不能别其他客户端删除)
- 死锁(获取锁的客户端由于某些原因宕机,导致其他客户端无法获取到该锁)
- 容错(当部分redis节点服务器宕机,客户端还是能够获取锁和释放锁)
常用解决方法:
- SETNX key value:如果key不存在,则创建并赋值。时间复杂度O(1)。设置成功返回1 ,设置失败返回0
问:如何解决setnx长期有效的问题?
EXPIRE key seconds 设置key的有效时间,当key过期(时间为0),会被自动删除 。
缺点:原子性不能满足!
伪代码如下:
注意代码种status==1 之后 程序挂掉 这个锁就是死锁了
2. set 原子操作方法(redis 2.6之后支持)
SET key value [EX seconds] [PX milliseconds][NX||XX]
EX second: 设置键的过期时间为second秒
Px millisecond:设置键的过期时间为millisecond毫秒
NX:只在键不存在的时候才对键进行设置操作
XX:只在键存在时候才对键进行设置操作
SET操作成功完成时,返回ok,否则返回nil
ps:设置value的时候可以设置成requestID 或者线程ID 可以标记获取锁的资源
伪代码如下:
问:大量的key同时过期的注意事项?
集中过期,由于清除大量的key很耗时,会出现短暂的卡顿现象
解决方法:在设置key的过期时间时,给每个key加上随机值,使得过期时间分散些