1.分布式锁需要解决的问题

  • 互斥性:任意时刻只能有一个客户端拥有锁,不能同时多个客户端获取
  • 安全性:锁只能被持有该锁的用户删除,而不能被其他用户删除
  • 死锁:获取锁的客户端因为某些原因而宕机,而未能释放锁,其他客户端无法获取此锁,需要有机制来避免该类问题的发生
  • 容错:当部分节点宕机,客户端仍能获取锁或者释放锁

2.如何通过Redis实现分布式锁:(非完善方法)

SETNX key value :如果key不存在,则创建并赋值
  • 时间复杂度: 0(1)
  • 返回值:设置成功,返回1;设置失败,返回0。

但是此时我们获取的key是长期有效的,所以我们应该如何解决长期有效的问题呢?

如何解决SETNX长期有效的问题

EXPIRE key seconds
  • 设置key的生存时间,当key过期时(生存时间为0) ,会被自动删除
  • 缺点:原子性得不到满足
下面是伪代码
//该程序存在危险,如果执行到第二行就崩溃了,则此时key会被一直占用而无法被释放
RedisService redisService = SpringUtils.getBean(Redi sService.class); 
long status = redisService.setnx(key, "1");
if(status == 1) {
	redisService.expire(key, expire);
	//执行独占资源逻辑
	doOcuppiedWork();
}

3.如何通过Redis实现分布式锁:(正确方式)

SET key value [EX seconds] [PX milliseconds] [NX|XX]
  • EX second :设置键的过期时间为second秒
  • PX millisecond :设置键的过期时间为millisecond毫秒
  • NX :只在键不存在时,才对键进行设置操作
  • XX:只在键已经存在时,才对键进行设置操作
  • SET操作成功完成时,返回OK ,否则返回nil
下面是伪代码
RedisService redisService = SpringUtils.getBean(RedisService.class); .
String result = redisService.set(lockKey, requestId, SET_IF_NOT_EXIST, SET_WITH_EXPIRE_TIME, expireTime);
if ("OK".equals(result)) {
	//执行独占资源逻辑
	doOcuppiedWork();
}

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

  • 集中过期,由于清除大量的key很耗时,会出现短暂的卡顿现象
  • 解放方案:在设置key的过期时间的时候,给每个key加上随机值

版权声明:本文为qq_38542085原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
原文链接:https://blog.csdn.net/qq_38542085/article/details/91818742