如何通过Redis实现分布式锁

分布式锁需要解决的问题

互斥性 任意时刻只能有一个客户端获取到锁
安全性 锁只能由拥有该锁的客户端删除
死锁 获取锁的客户端因为某些原因宕机而未能释放锁,而导致其他客户端再也无法获取到该锁
容错 部分节点宕机的时候Redis依然能够获取锁和释放锁

如何利用Redis实现分布式锁

在Redis中存在setnx key value的命令,如果key存在,则创建并赋值

  • 时间复杂度:O(1)
  • 返回值:设置成功,返回1;设置失败,返回0;

客户端通过去setnx(具有原子性)一个key的返回值来判断能否获取到锁

如何解决setnx长期有效的问题?

为什么需要解决长期有效的问题,线程异常,未正确释放。

expire key seconds

代码实现

long status = redisService.setnx(key,"1");
if(status == 1) {
    redisService.expire(key,seconds);
    //执行独占资源逻辑
    doOccupiedWork();
}

存在的问题

setnxexpire两个原子性操作联合起来不在具有原子性,如果在第三行代码执行过程中发生了中断,

那么这个key将一直不会过期。

解决方案

在Redis2.6之后,将setnxexpire融合了起来,使其具有原子性,具体操作如下。

SET key value [EX seconds] [PX milliseconds] [NX|XX]

  • EX second :设置键的过期时间为second秒
  • PX millisecond :设置键的过期时间为millisecond毫秒
  • NX :只在键不存在时,才对键进行设置操作
  • XX :只在键已经存在时,才对键进行设置操作
  • SET操作成功完成时,返回OK ,否则返回nil

代码实现

String result = redisService.set(lockKey,requestId,SET_IF_NOT_EXISTS,SET_WITH_EXPIRE_TIME,expireTime);
if("OK".equals(result)) {
    //执行独占资源逻辑
    doOccupiedWork();
}

大量的key同时过期的注意事项

存在的问题:集中过期,由于清除大量的key很耗时,会出现短暂的卡顿现象。

解放方案:在设置key的过期时间的时候,给每个key加上随机值

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容

友情链接更多精彩内容