编程技术网

关注微信公众号,定时推送前沿、专业、深度的编程技术资料。

 找回密码
 立即注册

QQ登录

只需一步,快速开始

极客时间

redis分布式锁总结

爱穿西装 云计算 2021-12-8 01:27 212人围观

腾讯云服务器

转自https://github.com/DragonV96/study-notes/

分布式锁总结

1 Redis 分布式锁

1.1 基础概念

1. 概念

官方叫做 RedLock 算法,是 Redis 官方支持的分布式锁算法。

2. 特性

该分布式锁有 3 个特性:

  • 互斥(只能有一个客户端获取锁)
  • 不能死锁
  • 容错(只要大部分 Redis 节点创建了这把锁就可以)

3. 实现方式

Redis 分布式锁的实现方式有两种:

  • Redis 最普通的分布式锁
  • RedLock 算法

1.2 Redis 最普通的分布式锁

1. 加锁

在 Redis 里使用 SET key value [EX seconds] [PX milliseconds] NX 创建一个 key,即加锁。

  • NX:表示只有 key 不存在的时候才会设置成功,如果此时 redis 中存在这个 key,那么设置失败,返回 nil
  • EX seconds:设置 key 的过期时间,精确到秒级。意思是 seconds 秒后锁自动释放,别人创建的时候如果发现已经有了就不能加锁了;
  • PX milliseconds:同样是设置 key 的过期时间,精确到毫秒级

示例:

SET xxx random_value PX 30000 NX
# 或者
SETNX xxx random_value PX 30000

2. 释放锁

释放锁即删除 key ,一般可以用 lua 脚本删除,判断 value 一样才删除:

-- 删除锁的时候,找到 key 对应的 value,跟自己传过去的 value 做比较,如果是一样的才删除。
if redis.call("get",KEYS[1]) == ARGV[1] then
    return redis.call("del",KEYS[1])
else
    return 0
end

3. 存在问题

用 random_value 随机值的原因:如果某个客户端获取到了锁,但是阻塞了很长时间才执行完,比如说超过了 30s,此时可能已经自动释放锁了,此时可能别的客户端已经获取到了这个锁,要是你这个时候直接删除 key 的话会有问题,所以得用随机值加上面的 lua 脚本来释放锁。

但是这样还是会有问题:

  • 如果是普通的 Redis 单实例,那就是单点故障
  • 如果是 Redis 普通主从,那 Redis 主从异步复制,如果主节点挂了(key 没有了),但是 key 还没同步到从节点,此时从节点切换为主节点,别的服务就可以 set key,从而拿到锁

4. 适用场景

单机 Redis 实例场景。

1.3 RedLock 算法

1. 流程

假设一个 Redis cluster,有 5 个 Redis master 实例。执行如下步骤获取一把锁:

①获取当前时间戳,单位是毫秒;

②跟上面类似,轮流尝试在每个 master 节点上创建锁,过期时间较短,一般就几十毫秒;

③尝试在大多数节点上建立一个锁,比如 5 个节点就要求是 3 个节点 n / 2 + 1 ;

④客户端计算建立好锁的时间,如果建立锁的时间小于超时时间,就算建立成功了;

⑤要是锁建立失败了,那么就依次将之前建立过的锁删除;

⑥只要别的服务建立了一把分布式锁,你就得不断轮询去尝试获取锁

2. 适用场景

Redis cluster(集群)场景。

2 zookeeper 分布式锁

腾讯云服务器 阿里云服务器
关注微信
^