通过redis实现分布式锁
实现分布式锁
分布式锁需要解决的问题
- 互斥性
- 任一时刻,只能有一个客户端获取锁
- 安全性
- 锁只能由持有的客户端删除
- 死锁
- 避免某些客户端因宕机等原因未能释放锁,而其他客户端再也无法获取该锁
- 容错
- 当部分节点宕机后客户端应仍然能够获取锁和释放锁
如何通过Redis实现分布式锁
方案一(不推荐)
SETNX key value
:如果key不存在,创建并赋值
- 时间复杂度O(1)
- 返回值:key不存在,设置成功,返回1,key存在则失败返回0
因为setnx是原子的又有以上特性,初期被用来实现分布式锁
执行某段代码时先尝试使用SETNX
对某个key设值,如果设置成功,则证明没有别的线程在执行该段代码。
如何解决SETNX
长期有效的问题?
EXPIRE key secons
- 设置key的生存时间,当key过期时会被自动删除
此方法的问题
如果一个线程设置了key还没来得及设置过期时间就宕机了,就会发生死锁
主要原因就是原子性不能得到满足
方案二
将SETNX
和EXPIRE
放在一块执行
SET key value [EX seconds] [PX milliseconds] [NX|XX]
EX seconds:设置键值对过期时间为seconds秒
PX milliseconds:设置键值对过期时间为milliseconds毫秒
NX:只在键不存在时才对键进行设置操作,效果等同
SETNX
XX:只在键已在时才对键进行设置操作,与
SETNX
相反SET操作完成时返回OK,否则返回nil
这样可以保证操作的原子性
大量key同时过期的注意事项
集中过期,由于清楚大量的key很耗时,会出现短暂卡顿现象
- 解决方法:在设置key的过期时间时,给每个key加一个随机值
本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来自 Alfred的小站!