分布式锁需要解决的问题:
- 互斥性:任意时刻只能有一个客户端获取锁
- 安全性:锁只能被持有该锁的客户端删除
- 死锁:获取锁的客户端因为意外宕机未能释放锁,其他客户端再也无法获取到该锁导致死锁
- 容错:宕机后客户端仍然可以获取、释放锁
SETNX key value:如果 key 不存在,即创建并赋值;
时间复杂度O(1);
返回值设置:设置成功返回1,设置失败返回0;
如何解决 SETNX 长期有效的问题?
EXPIRE key seconds
设置 key 的生存时间,当 key 过期时(生存时间为0),会被自动删除
RedisService redisService = SpringUtils.getBean(RedisService.class); long status = redisService.setnx(key,"1"); if(status == 1){ redisService.expire(key,expire); //执行独占资源逻辑 do0cuppiedWork(); }
缺点:原子性得不到满足
SET key value [EX seconds] [PX milliseconds] [NX|XX]
-EX seconds:设置键的过期时间为 second 秒
-PX milliseconds:设置键的过期时间为 milliseconds 毫秒
-NX:只在键不存在时,才对键进行设置操作
-XX:只在键已经存在时,才对键进行设置操作
-SET操作完成时,返回OK,否则返回nil
大量的 key 同时过期的注意事项
-集中过期,由于清除大量的 key 很耗时,会出现短暂的卡顿现象
-解决方案:在设置 key 的过期时间的时候,给每个 key 加上随机值