Redis分布式锁同步问题-Redlock
分布式锁知识回顾
业务场景
- 优惠券领券限制张数
- 商品库存超卖
- ……
起因
- 为了防止分布式系统中的多个进程之间相互干扰,我们需要一种分布式协调技术来对这些进程进行调度
- 利用互斥机制来控制共享资源的访问,这就是分布式锁要解决的问题
实现目标
保证同一时间只有一个客户端可以对共享资源进行操作。
解决方案
- Redis+Lua脚本
- 使用Redission框架(底层也是Lua+WatchDog机制)
Redis主从架构下的锁同步问题
生产环境下一般都是集群部署,则存在主从架构下的锁同步问题。
- 节点一在主节点获取分布式锁成功。
- Redis主节点再同步数据到从节点时宕机,数据没同步成功。
- 高可用机制则Redis从节点升级为主节点(但是没有锁信息)。
- 节点二在新的Redis上也成功获取分布式锁。
导致一个锁资源同时被两个节点获取,这个就出现了问题。
Redlock算法
Redis从3.0版本开始支持 Redlock算法,通过在多个 Redis 节点上创建同一个锁来防止主从节点之间出现的数据不一致的问题。
在 Redlock 算法中,需要从多个Redis节点获取锁,并对取锁结果进行校验,从而避免数据不一致性带来的问题。
锁变量由多个实例维护,即使有实例发生了故障,锁变量仍然是存在的,客户端还是可以完成锁操作。 需要注意的是,redlock算法会引入一定的错误率,需要根据业务场景进行权衡和控制
加锁流程
- 客户端 获取当前毫秒级时间戳,并设置超时时间 TTL
- 依次向 N 个 Redis 服务发出请求,用能够保证全局唯一的 value 申请锁 key
- 如果从 N/2+1个redis 服务中都获取锁成功,那本次分布式锁的获取被视为成功,否则获取锁失败
- 如果获取锁失败,或执行达到 TTL,则向所有 Redis 服务都发出解锁请求
- 如果想搭建一个能够允许 N 台机器 down 掉的集群,那么就要部署一个由 2*N+1 台服务器构成的集群。
- 高可用部署最少的节点数计算公式: N(总节点数)=2*X(宕机数)+1,X>0,最少需要3台,半数以上节点选举,不包含半数”
宕机一台还可以高可用:3=2*1+1
宕机二台还可以高可用:5=2*2+1
注意
- 这种架构上redis全部节点都是主节点,没有从节点,抛弃了主从的异步复制
- 各个节点之间没关系,不是集群也不是主从,互相独立
- 由于使用比较复杂且概率性较低,但多数公司还是采用了主从架构
- 在一些特定的场景且要求高的情况才会采用,且节点数会根据情况增加
Redlock环境准备
节点 | 端口号 |
---|---|
redlock-1 | 6380 |
redlock-2 | 6381 |
redlock-3 | 6382 |
docker镜像加速配置
自 2024-06-06 开始,国内的 Docker Hub 镜像加速器相继停止服务,可选择为 Docker daemon 配置代理或自建镜像加速服务。
sudo mkdir -p /etc/docker
sudo tee /etc/docker/daemon.json <<-'EOF'
{
"registry-mirrors": [
"https://docker.m.daocloud.io",
"https://mirror.baidubce.com",
"https://docker.nju.edu.cn",
"https://mirror.iscas.ac.cn",
"https://88bit3po.mirror.aliyuncs.com"
]
}
EOF
sudo systemctl daemon-reload
sudo systemctl restart docker
部署3个redis服务
# 6380
docker run -itd --name redlock-1 -p 6380:6379 redis:7.0.8 --requirepass 123456
# 6381
docker run -itd --name redlock-2 -p 6381:6379 redis:7.0.8 --requirepass 123456
# 6382
docker run -itd --name redlock-3 -p 6382:6379 redis:7.0.8 --requirepass 123456