目录

Life in Flow

知不知,尚矣;不知知,病矣。
不知不知,殆矣。

X

Redis分布式锁同步问题-Redlock

分布式锁知识回顾

image.png

业务场景

  • 优惠券领券限制张数
  • 商品库存超卖
  • ……

起因

  • 为了防止分布式系统中的多个进程之间相互干扰,我们需要一种分布式协调技术来对这些进程进行调度
  • 利用互斥机制来控制共享资源的访问,这就是分布式锁要解决的问题

实现目标

保证同一时间只有一个客户端可以对共享资源进行操作。

解决方案

  • Redis+Lua脚本
  • 使用Redission框架(底层也是Lua+WatchDog机制)

Redis主从架构下的锁同步问题

image.png

生产环境下一般都是集群部署,则存在主从架构下的锁同步问题。

  1. 节点一在主节点获取分布式锁成功。
  2. Redis主节点再同步数据到从节点时宕机,数据没同步成功。
  3. 高可用机制则Redis从节点升级为主节点(但是没有锁信息)。
  4. 节点二在新的Redis上也成功获取分布式锁。

导致一个锁资源同时被两个节点获取,这个就出现了问题。

Redlock算法

官方文档

Redis从3.0版本开始支持 Redlock算法,通过在多个 Redis 节点上创建同一个锁来防止主从节点之间出现的数据不一致的问题。

在 Redlock 算法中,需要从多个Redis节点获取锁,并对取锁结果进行校验,从而避免数据不一致性带来的问题。

锁变量由多个实例维护,即使有实例发生了故障,锁变量仍然是存在的,客户端还是可以完成锁操作。 需要注意的是,redlock算法会引入一定的错误率,需要根据业务场景进行权衡和控制

加锁流程

  1. 客户端 获取当前毫秒级时间戳,并设置超时时间 TTL
  2. 依次向 N 个 Redis 服务发出请求,用能够保证全局唯一的 value 申请锁 key
  3. 如果从 N/2+1个redis 服务中都获取锁成功,那本次分布式锁的获取被视为成功,否则获取锁失败
  4. 如果获取锁失败,或执行达到 TTL,则向所有 Redis 服务都发出解锁请求

image.png

  • 如果想搭建一个能够允许 N 台机器 down 掉的集群,那么就要部署一个由 2*N+1 台服务器构成的集群。
  • 高可用部署最少的节点数计算公式: N(总节点数)=2*X(宕机数)+1,X>0,最少需要3台,半数以上节点选举,不包含半数”
    宕机一台还可以高可用:3=2*1+1
    宕机二台还可以高可用:5=2*2+1

注意

  • 这种架构上redis全部节点都是主节点,没有从节点,抛弃了主从的异步复制
  • 各个节点之间没关系,不是集群也不是主从,互相独立
  • 由于使用比较复杂且概率性较低,但多数公司还是采用了主从架构
  • 在一些特定的场景且要求高的情况才会采用,且节点数会根据情况增加

Redlock环境准备

节点端口号
redlock-16380
redlock-26381
redlock-36382

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

作者:Soulboy