文章目录
- 一、对 Redis Sentinel 的认识
- 1.1 什么是 Redis Sentinel
- 1.2 为什么要使用 Redis Sentinel
- 1.2.1 主从复制问题
- 1.2.2 人工恢复主节点故障
- 二、Redis Sentinel 原理剖析
- 2.1 Redis Sentinel 架构
- 2.2 Raft 算法和领袖节点
- 2.3 哨兵节点
- 2.4 故障检测
- 2.5 故障切换
- 2.6 监控和通知
- 三、基于 Docker 模拟搭建 Redis 主从结构和哨兵分布式架构
- 3.1 准备工作
- 3.1.1 安装 Docker 和 Docker Compose
- 3.1.2 停止 Redis 服务
- 3.1.3 获取 Redis 镜像
- 3.2 基于 Docker 模拟搭建 Redis 主从结构
- 3.2.1 使用 Docker-Compose 编排 Redis 主从节点
- 3.2.2 启动 Redis 主从容器
- 3.2.3 查看容器运行日志
- 3.2.4 连接Redis 主从服务器
- 3.2.5 停止或销毁容器
- 3.3 基于 Docker 模拟搭建 Redis 哨兵分布式架构
- 3.3.1 创建 Sentinel 配置文件
- 3.3.2 使用 Docker-Compose 编排 Redis 哨兵节点
- 3.3.3 启动 Redis 哨兵容器
- 3.3.4 启动后的 Sentinel 配置文件
- 3.3.5 在分布式架构中,为什么设置多个哨兵节点
- 四、演示哨兵机制的主从自动切换
- 4.1 停止 Redis 主节点
- 4.2 重新选举的主节点
- 4.3 查看哨兵节点日志
- 4.4 领袖哨兵的选举原理
- 4.5 新主节点的选举原理
- 五、哨兵机制存在的缺陷
一、对 Redis Sentinel 的认识
1.1 什么是 Redis Sentinel
Redis Sentinel(Redis 哨兵)是一个用于监控和管理 Redis 高可用性(High Availability)的系统。它是 Redis 官方提供的一种解决方案,用于确保 Redis 在面临主节点故障等异常情况时能够自动进行故障切换,保持系统的可用性。
Redis Sentinel 的主要功能包括:
- 监控: Sentinel 节点会定期检查 Redis 主从节点的健康状态,以确保它们正常运行。
- 故障检测: Sentinel 可以检测到主节点的故障,并快速将其切换到备用的从节点,以避免服务中断。
- 自动故障切换: Sentinel 负责选举新的主节点,并自动将其它从节点配置为新的主节点的从节点,实现自动故障切换。
- 通知: Sentinel 可以向管理员发送通知,通知他们关于 Redis 集群的状态变化和故障情况。
Redis Sentinel 相关名词解释:
名词 | 逻辑结构 | 物理结构 |
---|---|---|
主节点 | Redis 主节点是一个Redis服务器,负责处理客户端请求。 | Redis 主节点是一个独立的 redis-server 进程。 |
从节点 | Redis 从节点是一个Redis服务器,它复制主节点的数据。 | Redis 从节点是一个独立的 redis-server 进程。 |
Redis 数据节点 | Redis 数据节点通常指主节点和从节点的组合。 | Redis数据节点包括主节点和从节点的 redis-server 进程。 |
哨兵节点 | Redis Sentinel 节点是用于监视 Redis 数据节点状态的节点。 | Redis Sentinel节点是一个独立的 redis-sentinel 进程。 |
哨兵节点集合 | 哨兵节点集合是若干个 Redis Sentinel 节点的抽象组合。 | 哨兵节点集合包括多个独立的 redis-sentinel 进程。 |
Redis 哨兵(Sentinel) | Redis Sentinel 是 Redis 提供的高可用方案,包括哨兵节点集合和 Redis 主从应用方案。 | Redis Sentinel 包括哨兵节点集合和 Redis主从应用方案。 |
Redis 主从应用方案 | Redis 主从应用方案是指使用 Redis 主节点和从节点来构建高可用的 Redis 架构。 | Redis 主从应用方案包括主节点和从节点的 redis-server 进程。 |
希望这个表格能够帮助您更清晰地理解这些名词以及它们的逻辑和物理结构。如果您还有其他问题或需要进一步的解释,请随时提问。
1.2 为什么要使用 Redis Sentinel
使用 Redis Sentinel 主要是为了解决 Redis 在分布式环境下可能出现的高可用性问题,特别是在以下方面:
1.2.1 主从复制问题
Redis 的主从复制模式确实可以提供一定的高可用性和读负载均衡,但也存在一些问题,特别是在主备切换方面,以及对写压力的限制。以下是对这些问题的详细解释:
-
主备切换的复杂性:当 Redis 主节点发生故障或不可达时,进行主备切换是一个复杂的过程。通常需要完全的人工参与,这会导致故障恢复时间无法保障。主备切换过程包括检测主节点的故障、选举新的主节点、通知客户端和从节点切换等多个步骤。为了解决这个问题,Redis 引入了 Redis Sentinel(哨兵),它是一组独立的进程,专门用于监控和管理 Redis 数据节点的状态。哨兵可以自动执行主备切换,从而提高了高可用性。
-
写压力无法分担:在传统的主从复制模式中,主节点仍然需要承担所有的写请求,因此写压力仍然受到单个主节点的限制。无法将写压力分散到多个节点上。为了解决这个问题,可以考虑使用Redis Cluster(Redis集群)。Redis Cluster 是一种分布式模式,它将数据分片到多个节点上,并允许在多个节点上进行写操作,从而提供更好的写扩展性和数据分布。这样,可以通过增加节点数量来增加写容量。
总结来说,主从复制模式是一个有用的工具,但它不是解决所有问题的终极解决方案。主备切换的复杂性和写压力限制是其存在的问题。为了提高高可用性和写扩展性,可以使用 Redis Sentinel 来自动处理主备切换,并考虑使用 Redis Cluster 来分担写压力。根据实际需求和场景,可以选择合适的 Redis 架构。
1.2.2 人工恢复主节点故障
在没有Redis Sentinel的情况下,主节点发生故障后,通常需要进行人工干预以完成主从切换的操作。这会增加系统的维护成本和风险,并且依赖于管理员的实时监控和手动操作。
下面是人工处理主节点故障的大致过程的详细描述:
1. 正常状态下的主从节点
在正常情况下,Redis配置了主从节点,其中主节点处理写请求,而从节点充当备份。
2. 检测主节点宕机
当程序员或系统管理员发现主节点宕机时,通常是通过监控系统或日志来发现的。
3. 选择新的主节点
在发现主节点故障后,管理员需要手动选择一个从节点作为新的主节点。这个选择通常基于管理员的判断和决策。
4. 配置从节点
管理员需要将其他从节点重新配置为新主节点的从节点。这个过程需要手动进行,并且可能需要更新配置文件和重新启动Redis进程。
5. 更新应用程序连接
应用程序需要重新配置以连接到恢复后的新主节点,以便继续对 Redis 进行操作。
6. 恢复原主节点
最后,宕机的原主节点可以进行修复,并将其重新添加为新主节点的从节点。这个过程同样需要管理员手动操作。
需要注意的是,这个过程需要管理员的及时响应和操作。如果主节点故障发生在非工作时间或管理员不可用的情况下,可能会导致系统的不可用性。为了自动化这个过程并提高高可用性,Redis Sentinel 用于监控和自动处理主备切换,减少了人工干预的需要。这是提高 Redis 系统可靠性的一种重要方式。
二、Redis Sentinel 原理剖析
2.1 Redis Sentinel 架构
Redis Sentinel的架构如下图所示:
相对于简单的主从复制模式,Redis Sentinel 引入了若干(建议保持奇数个,以利于哨兵节点之间投票选举领袖节点)Sentinel 节点,用于监控数据节点。这些哨兵节点定期监测所有节点,包括数据节点和其他哨兵节点。当主节点发生故障时,故障切换的流程大致如下:
-
主节点发生故障,导致与从节点的同步连接中断,主从复制停止。
-
哨兵节点通过定期监测发现主节点故障。哨兵节点开始与其他哨兵节点进行协商,以达成多数认同主节点故障的共识。这一步骤的主要目的是防止出现这种情况:主节点未发生故障,但监测故障的哨兵节点由于网络问题被孤立。
-
哨兵节点之间使用 Raft 算法进行选举,选出一个领袖节点,领袖节点负责后续的故障转移工作。
-
哨兵领袖节点开始执行故障转移操作:选择一个从节点作为新的主节点,让其他从节点同步新的主节点数据,然后通知应用层将连接切换到新的主节点。
通过上面的介绍,可以看出 Redis Sentinel 具有以下几个功能:
- 监控: Sentinel 节点会定期检测 Redis 数据节点、其余哨兵节点是否可达。
- 主节点故障转移: 实现从节点晋升(promotion)为主节点并维护后续正确的主从关系。
- 通知: Sentinel 节点会将故障转移的结果通知给应用方。
- 配置提供者: 在 Redis Sentinel 结构中,客户端连接的是哨兵节点,从中获取主节点信息,而不是直接连接主节点。这一点在使用代码编程的时候能够体现到。
2.2 Raft 算法和领袖节点
Raft 算法:
- Raft 算法是一种共识算法,用于在分布式系统中实现一致性和高可用性。它是一种相对较新且较易理解的算法,于 2013 年由 Diego Ongaro 和 John Ousterhout 提出。Raft 的设计目标是提供更容易理解和实现的一致性算法,与 Paxos 等经典算法相比更具可读性。
- Raft 算法的主要思想是通过选举一个领袖节点(leader)来达成一致性,领袖节点负责处理客户端请求,并确保系统中的所有节点达成一致的状态。
领袖节点:
哨兵领袖节点(Sentinel Leader Node)是在 Redis Sentinel 集群中被选举出来负责协调和执行故障转移操作的特殊哨兵节点。当 Redis 主节点发生故障时,哨兵节点会进行选举,其中被选为领袖的哨兵节点将领导整个故障切换过程。
以下是哨兵领袖节点的主要职责和功能:
-
领导故障切换过程: 当主节点发生故障时,哨兵领袖节点负责领导并协调故障切换操作。这包括选择一个从节点作为新的主节点、通知其他哨兵节点和客户端进行切换。
-
发起故障转移: 哨兵领袖节点会发起故障转移操作,确保新的主节点能够接管服务。这包括将一个从节点升级为主节点,并协调其他从节点进行数据同步。
-
通知客户端: 哨兵领袖节点负责通知客户端切换到新的主节点,以便继续提供服务。这确保了在主节点发生故障时,客户端能够无缝切换到新的主节点,维护了系统的连续性。
-
与其他哨兵节点协作: 哨兵领袖节点与其他哨兵节点进行协作,以确保选举过程的稳定性和一致性。它们使用Raft算法等机制来选举领袖节点,并在切换过程中达成共识。
哨兵领袖节点在 Redis Sentinel 中起着关键的作用,它们的存在确保了故障转移操作能够以一致的方式进行,同时提供高可用性和自动化的管理。如果领袖节点本身发生故障,其他哨兵节点将会重新选举一个新的领袖来继续执行任务。这种设计保证了 Redis Sentinel 的可靠性和弹性。
2.3 哨兵节点
哨兵节点是 Redis Sentinel 架构中的重要组成部分。它们的主要任务是监控 Redis 数据节点的状态,检测主节点是否发生故障,并协调故障恢复过程。
每个哨兵节点都会独立执行以下任务:
- 定期检测 Redis 数据节点的可用性,包括主节点和从节点。
- 监控 Redis 数据节点的配置,确保配置信息一致。
- 发现主节点故障并通知其他哨兵节点,以便协调故障切换操作。
- 通过选举算法(通常采用 Raft 算法)选出一个领袖哨兵节点,负责执行故障转移操作。
- 向应用层通知故障发生以及故障切换的结果。
2.4 故障检测
Redis Sentinel 负责检测 Redis 数据节点的故障。它通过以下方式进行故障检测:
- 哨兵节点定期向 Redis 数据节点发送 PING 命令,以确保节点的可用性。
- 如果一个 Redis 数据节点在一定时间内未响应,哨兵节点会将该节点标记为主观下线(subjectively down)。
- 当多数哨兵节点都将某个节点标记为主观下线时,该节点会被视为客观下线(objectively down)。
- 哨兵节点会定期检查客观下线的节点,如果该节点重新变为可用状态,则哨兵会将其标记为上线。
2.5 故障切换
当主节点发生故障时,Redis Sentinel 负责执行故障切换操作,将一个从节点晋升为新的主节点。这个过程包括以下步骤:
- 哨兵节点检测到主节点故障,并与其他哨兵节点协商,选举出一个领袖哨兵节点。
- 领袖哨兵节点选择一个从节点作为新的主节点,并通知其他从节点开始复制新的主节点数据。
- 应用层被通知切换到新的主节点,继续提供服务。
2.6 监控和通知
Redis Sentinel 提供了监控和通知功能,确保管理员和应用层能够及时获得关于 Redis 集群状态的信息。监控和通知包括以下内容:
- 哨兵节点会定期向应用层发送关于 Redis 数据节点的信息,包括主节点地址、从节点地址等。
- 当主节点故障时,哨兵节点会通知应用层进行故障切换。
- 哨兵节点可以将关于 Redis 集群状态的信息发布到外部系统,供管理员进行监控和分析。
三、基于 Docker 模拟搭建 Redis 主从结构和哨兵分布式架构
3.1 准备工作
3.1.1 安装 Docker 和 Docker Compose
我的云服务器版本是 Ubuntu 22.04 LTS,在 Ubuntu 22.04 LTS 上安装 Docker 可以按照以下步骤进行:
注意:在开始安装 Docker 之前,请确保是以 root 用户或具有 sudo 权限的用户身份登录到系统。
- 更新软件包列表:
sudo apt update
- 安装依赖包,以支持HTTPS:
sudo apt install apt-transport-https ca-certificates curl software-properties-common
- 添加 Docker 官方存储库的GPG密钥:
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /usr/share/keyrings/docker-archive-keyring.gpg
- 添加 Docker 官方存储库:
echo "deb [arch=amd64 signed-by=/usr/share/keyrings/docker-archive-keyring.gpg] https://download.docker.com/linux/ubuntu $(lsb_release -cs) stable" | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
- 再次更新软件包列表:
sudo apt update
- 安装 Docker:
sudo apt install docker-ce docker-ce-cli containerd.io
- 启动Docker服务:
sudo systemctl start docker
- 将Docker添加到系统启动项,使其在系统重启时自动启动:
sudo systemctl enable docker
- 验证Docker是否成功安装:
sudo docker --version
这将显示安装的Docker版本信息。
- (可选) 如果希望非 root 用户能够运行 Docker 命令,可以将该用户添加到 docker 组:
sudo usermod -aG docker $USER
注意,必重新登录或注销以使组更改生效。
至此,已成功在 Ubuntu 22.04 LTS 上安装了 Docker,可以开始使用Docker来运行容器化的应用程序。如果需要更多 Docker 命令和示例,可以参考 Docker 官方文档。
安装 Docker-Compose:
安装步骤如下:
- 更新包列表:
sudo apt update
- 安装Docker Compose:
sudo apt install docker-compose
- 验证 Docker Compose 是否已成功安装:
docker-compose --version
这将显示已安装的 Docker Compose 版本信息。
现在,已经使用 APT 包管理器在 Ubuntu 22.04 LTS 上成功安装了 Docker Compose。 可以使用 docker-compose
命令来管理和运行容器化应用程序的多个服务。
3.1.2 停止 Redis 服务
在使用 Docker 搭建Redis 哨兵的时候,停止系统中原来的 Redis 服务是为了防止端口冲突。首先可以使用 PS 命令在查看运行中的 Redis 服务进程。
ps -axj | grep redis-server
然后在使用 service redis-server stop
命令或者 kill
命令来终止 Redis 服务进程。
3.1.3 获取 Redis 镜像
要获取 Redis 镜像,可以使用 docker pull
命令。例如,以下是获取 Redis 5.0.9 镜像的步骤:
docker pull redis:5.0.9
这将从 Docker Hub 下载 Redis 5.0.9 镜像并存储在本地系统中。如果要不同版本的 Redis 镜像,只需将命令中的版本号替换为想要的版本号即可。
一旦下载完成,可以使用 docker images
命令来查看已下载的镜像列表:
docker images
此时,将在列表中看到已下载的 Redis 镜像,包括标签为 5.0.9 的镜像。现在,就可以使用这个镜像来创建 Redis 容器并进行相关操作了。
3.2 基于 Docker 模拟搭建 Redis 主从结构
3.2.1 使用 Docker-Compose 编排 Redis 主从节点
首先创建一个 redis
目录,再在这个目录创建一个 redis-data
,该目录下存放编排 Redis 主从节点的 YML 文件。
mkdir redis
cd redis
mkdir redis-data
编写 docker-compose.yml
文件
在 redis-data
目录下创建一个 YML 文件 docker-compose.yml
,然后写入以下内容:
version: '3.7'
services:
master:
image: 'redis:5.0.9'
container_name: redis-master
restart: always
command: redis-server --appendonly yes
ports:
- 6379:6379
slave1:
image: 'redis:5.0.9'
container_name: redis-slave1
restart: always
command: redis-server --appendonly yes --slaveof redis-master 6379
ports:
- 6380:6379
slave2:
image: 'redis:5.0.9'
container_name: redis-slave2
restart: always
command: redis-server --appendonly yes --slaveof redis-master 6379
ports:
- 6381:6379
docker-compose.yml
文件是 Docker-Compose 用于编排管理容器的,在上述的 YML 文件中,定义了一个使用 Redis 的 Docker 容器化应用程序,其中包括一个主 Redis 实例和两个从 Redis 实例。
以下是该docker-compose.yml
文件的主要配置说明:
-
version: '3.7'
: 指定了 Docker Compose 文件的版本。 -
services
: 定义了三个服务,分别是master
、slave1
和slave2
。每个服务对应一个 Docker 容器。 -
master
: 主 Redis 实例的配置。image: 'redis:5.0.9'
: 使用 Redis 5.0.9 的官方 Docker 镜像。container_name: redis-master
: 设置容器的名称为redis-master
。restart: always
: 如果容器意外停止,始终重新启动容器。command: redis-server --appendonly yes
: 启动容器时执行的命令,开启了 Redis 的持久化选项。ports: - 6379:6379
: 将容器的 6379 端口映射到主机的 6379 端口,允许通过主机访问 Redis 服务。
-
slave1
和slave2
: 两个从Redis实例的配置。它们与主 Redis 实例相似,但还包括了--slaveof
选项,将它们配置为主 Redis 实例的从节点,从而实现 Redis 数据的复制。command: redis-server --appendonly yes --slaveof redis-master 6379
: 启动容器时执行的命令,将容器配置为主 Redis 实例的从节点。ports: - 6380:6379
和ports: - 6381:6379
: 将两个从 Redis 容器的 6379 端口映射到不同的主机端口,以便它们可以通过不同的端口访问。
通过使用这个 docker-compose.yml
文件,可以轻松地启动一个包含主从 Redis 实例的 Docker 化应用程序,用于实现 Redis 数据的高可用性和冗余备份。
3.2.2 启动 Redis 主从容器
要启动上面编排的 Redis 主从容器需要使用到 docker-compose
命令,注意使用次命令使需要在 docker-compose.yml
文件的同一个目录之下。
下面是启动容器的命令:
docker-compose up -d
说明:
-
docker-compose
: 这是 Docker Compose 命令的名称,用于管理多个 Docker 容器的部署。 -
up
: 这是 Docker Compose 命令的子命令,用于启动服务。 -
-d
或--detach
: 这是一个选项,用于告诉 Docker Compose 以后台模式启动容器,不会在终端上显示容器的日志输出。
如果一切正常,Redis 主从容器将在后台运行,并且主从数据同步将开始进行。可以使用以下命令查看正在运行的容器:
docker ps
docker ps
命令用于列出正在运行的Docker容器。这个命令会显示容器的一些基本信息,如容器ID、镜像、状态、端口映射等等。
以下是常用的 docker ps
命令及其一些常用选项:
docker ps
: 列出所有正在运行的容器。docker ps -a
或docker ps --all
: 列出所有容器,包括正在运行和已停止的容器。docker ps -q
或docker ps --quiet
: 仅显示容器ID,适用于需要获取容器 ID 的脚本或命令。docker ps -l
或docker ps --latest
: 显示最近创建的容器。docker ps --filter
: 使用过滤器选项来筛选容器列表,例如,docker ps --filter "status=running"
可以列出所有正在运行的容器。docker ps --format
: 自定义输出格式,可以使用--format
选项指定要显示的字段。
3.2.3 查看容器运行日志
docker-compose logs
命令用于查看 Docker Compose 项目中所有服务的日志输出。默认情况下,它会显示所有服务的日志,但也可以通过指定服务的名称来查看特定服务的日志。
以下是一些常用的docker-compose logs
命令示例:
- 查看所有服务的日志:
docker-compose logs
- 查看特定服务的日志(替换"serviceName"为服务的实际名称):
docker-compose logs serviceName
- 查看最新的N行日志(使用
-n
选项,替换"N"为所需的行数):
docker-compose logs -n N
- 查看以前已停止的容器的日志(使用
-f
选项,仅显示新日志):
docker-compose logs -f
docker-compose logs
命令将显示每个容器的日志输出,包括标准输出和标准错误。这对于诊断容器问题、查找错误消息以及监视应用程序的运行非常有用。
请注意,如果使用docker-compose up -d
在后台模式启动了容器,可以使用docker-compose logs
来查看容器的日志。如果容器正在前台运行(即没有使用-d
选项),则可以使用docker logs
命令来查看容器的日志,后跟容器的名称或容器 ID。
例如,查看当前运行的容器的日志:
3.2.4 连接Redis 主从服务器
此时,可以使用 redis-cli -p xxxx
命令来连接指定的 Redis 服务器节点,例如:
当前主机中的端口号为 6379 的服务器是主节点,它现在拥有两个从节点,其 IP 分别为:172.21.0.3
和 172.21.0.4
。该IP 由 Docker 分配。
当前主机中端口号为 6380 对应的服务器是一个从节点,其主节点为上文的那个节点。
3.2.5 停止或销毁容器
停止或销毁 Docker 容器是在 Docker 环境中管理容器的常见操作之一。可以使用以下命令来停止或销毁容器:
- 停止容器:
使用docker stop
命令可以停止一个正在运行的容器。您需要提供容器的名称或容器ID作为参数。
示例:
docker stop containerNameOrID
这将停止指定的容器,但不会删除它,容器的状态将变为"Exited"。
- 启动容器:
使用docker start
命令可以重新启动一个已经停止的容器。
示例:
docker start containerNameOrID
这将重新启动指定的容器。
- 销毁容器:
使用docker rm
命令可以销毁一个已经停止的容器,从而删除容器的文件系统和元数据。
示例:
docker rm containerNameOrID
请注意,销毁容器会删除容器的数据和配置,所以请谨慎使用。
- 停止并销毁容器:
如果希望停止并销毁一个容器,可以组合使用docker stop
和docker rm
命令,如下所示:
docker stop containerNameOrID
docker rm containerNameOrID
这将首先停止容器,然后删除容器。
- 停止或销毁所有容器:
如果要停止或销毁所有正在运行的容器,可以使用以下命令:
停止所有容器:
docker stop $(docker ps -aq)
销毁所有容器:
docker rm $(docker ps -aq)
这将遍历所有容器并执行相应的操作。
另外,可以使用 docker-compose down
命令用于停止和删除由 docker-compose up
启动的所有服务和容器,同时清除相关的网络和卷。
docker-compose down
这是用于停止和清理 Docker Compose 项目的常见命令。与 docker stop
和 docker rm
命令不同,docker-compose down
是特定于 Docker Compose 项目的,可以一次性停止和删除整个项目的所有容器。
3.3 基于 Docker 模拟搭建 Redis 哨兵分布式架构
3.3.1 创建 Sentinel 配置文件
在上面创建的 redis
目录下,分别创建 sentinel1.conf
、sentinel2.conf
、sentinel3.conf
三个 Sentinel 的配置文件,分别对应三个哨兵节点,其初始内容完全相同如下:
bind 0.0.0.0
port 26379
sentinel monitor redis-master redis-master 6379 2
sentinel down-after-milliseconds redis-master 1000
这些配置项的含义如下:
bind 0.0.0.0
:允许哨兵节点绑定到所有网络接口,以接收来自任何 IP 的连接。port 26379
:指定哨兵节点监听的端口。sentinel monitor redis-master redis-master 6379 2
:设置监控的主 Redis 服务器的名称为redis-master
,其IP地址为redis-master
,端口号为6379
,并设置在 2 秒内未收到心跳信号时将主服务器标记为不可用。sentinel down-after-milliseconds redis-master 1000
:指定主服务器在 1 秒内未响应时被认为是不可用的时间。
另外需要注意的是,一旦哨兵节点运行起来,其配置文件内容会在运行时动态生成并改变。如果需要对哨兵的配置进行修改,应该在停止哨兵节点后修改配置文件,并在启动之前确保配置项的正确性。
对 sentinel monitor
的理解:
sentinel monitor 主节点名 主节点ip 主节点端口 法定票数
- 主节点名: 这是哨兵内部用于标识主节点的名称。每个主节点都应该在哨兵配置中具有唯一的主节点名。
- 主节点ip: 这是部署 Redis 主节点的设备的 IP 地址。如果你正在使用 Docker,你可以直接使用容器的名称,哨兵会自动解析成相应容器的 IP 地址。
- 主节点端口: 这是 Redis 主节点所监听的端口号,用于与主节点通信。
- 法定票数: 哨兵需要判定主节点是否宕机。有时候,因为特殊情况,如哨兵节点自身的网络问题导致无法访问主节点,可能会误判主节点宕机。为了确保稳定性,采用投票机制来决定是否确认主节点宕机。需要多个哨兵节点都认为主节点宕机,票数大于等于法定票数之后,才会真正确认主节点宕机状态。
对 sentinel down-after-milliseconds
的理解:
sentinel down-after-milliseconds redis-master 超时时间
主节点和哨兵之间通过心跳包进行通信。如果心跳包在指定的时间内未收到响应,就会被视为节点发生故障。这个参数用于设置哨兵等待多少毫秒来判断主节点是否宕机。
3.3.2 使用 Docker-Compose 编排 Redis 哨兵节点
在上面创建的 redis
目录下创建一个 redis-sentinel
目录,用于存放编排 Redis 哨兵节点的 YML 文件及其配置文件。
mkdir redis-sentinel
当然,也可以在上文的YML文件中继续编写关于编排 Redis 哨兵节点的配置,但是为了更好的查看各自的运行日志,因此分开编写。
编写 docker-compose.yml
文件:
在 redis-data
目录下创建一个 YML 文件 docker-compose.yml
,然后写入以下内容:
version: '3.7'
services:
sentinel1:
image: 'redis:5.0.9'
container_name: redis-sentinel-1
restart: always
command: redis-sentinel /etc/redis/sentinel.conf
volumes:
- ./sentinel1.conf:/etc/redis/sentinel.conf
ports:
- 26379:26379
sentinel2:
image: 'redis:5.0.9'
container_name: redis-sentinel-2
restart: always
command: redis-sentinel /etc/redis/sentinel.conf
volumes:
- ./sentinel2.conf:/etc/redis/sentinel.conf
ports:
- 26380:26379
sentinel3:
image: 'redis:5.0.9'
container_name: redis-sentinel-3
restart: always
command: redis-sentinel /etc/redis/sentinel.conf
volumes:
- ./sentinel3.conf:/etc/redis/sentinel.conf
ports:
- 26381:26379
# 当前所有容器加入 redis—data 容器的局域网
networks:
default:
external:
name: redis-data_default
上面的docker-compose.yml
文件定义了三个 Redis Sentinel 容器,这些容器用于监控 Redis 主从节点,以确保 Redis 的高可用性。并且 Redis Sentinel 是 Redis 官方提供的高可用性解决方案之一。
以下是关于 docker-compose.yml
文件中的主要配置说明:
-
version: '3.7'
: 指定了 Docker Compose 文件的版本。 -
services
: 定义了三个 Redis Sentinel 服务,分别是sentinel1
、sentinel2
和sentinel3
。每个服务对应一个 Redis Sentinel 容器。 -
每个 Sentinel 服务使用了 Redis 5.0.9 的官方 Docker 镜像,并将容器命名为
redis-sentinel-1
、redis-sentinel-2
和redis-sentinel-3
。-
restart: always
:如果容器意外停止,Docker 将始终重新启动这些容器。 -
command: redis-sentinel /etc/redis/sentinel.conf
:容器启动时执行的命令,用于启动 Redis Sentinel,并指定 Sentinel 配置文件的路径。 -
volumes
:将 Sentinel 配置文件挂载到容器的/etc/redis/sentinel.conf
路径。这允许我们自定义每个 Sentinel 的配置。 -
ports
:将容器的 26379 端口映射到主机的 26379、26380和26381 端口,以便可以通过主机访问 Sentinel 服务。
-
-
networks
:让当前所有的哨兵容器都加入到 局域网为redis-data_default
的 Docker 网络,这是上文启动 Redis 主从节点时创建的局域网。因为使用不同的docker-compose.yml
文件启动的局域网会不同,因此通过加入局域网的方法允许这些容器可以在同一个局域网内相互通信。
这个docker-compose.yml
文件用于启动三个Redis Sentinel容器,每个容器都配置了自己的 Sentinel 配置文件,并且它们可以协同工作来监控 Redis 主从容器,确保高可用性。
3.3.3 启动 Redis 哨兵容器
和上文启动 Redis 主从节点的容器一样,使用 docker-compose
命令来启动:
docker-compose up -d
查看日志:
以下是一些关于这些日志的解释:
redis-sentinel-1
、redis-sentinel-2
和redis-sentinel-3
是三个哨兵节点的容器名称。- 每个哨兵节点都在运行,并且它们已经监视了名为
redis-master
的主节点。 +monitor
行表示哨兵已经开始监视主节点,并且需要至少 2 个哨兵节点达成一致才能进行故障切换。+sdown
行表示有节点(主节点、从节点或其他哨兵节点)已被哨兵节点标记为下线。
使用 docker ps
查看运行中的容器:
至此,基于 Docker 模拟搭建 Redis 主从结构和哨兵分布式架构就成功了。
3.3.4 启动后的 Sentinel 配置文件
当启动了哨兵节点之后,再次观察刚才创建的 Sentinel配置文件 ,以 sentinel1.conf
为例:
可以看到在启动哨兵节点后,sentinel1.conf
文件的内容发生了明显的变化。以下是对这些变化的分析和解释:
-
sentinel myid
:每个哨兵节点在启动时都会生成一个唯一的 ID,并在配置文件中记录。这个 ID 用于区分不同的哨兵节点。 -
sentinel deny-scripts-reconfig yes
:这是一个安全配置,用于禁止通过脚本重新配置哨兵节点。这可以提高安全性,防止未经授权的修改。 -
dir "/data"
:这个配置指定了哨兵节点用于存储持久化数据的目录。在这里,哨兵节点将持久化数据存储在/data
目录中。 -
sentinel config-epoch
和sentinel leader-epoch
:这些配置项用于维护哨兵节点的配置信息。config-epoch
表示当前的配置纪元,leader-epoch
表示当前的领导者(leader)纪元。这些信息用于在多个哨兵节点之间协调配置更改。 -
sentinel known-replica
:这些配置项列出了已知的从节点,它们是主节点的复制品。在这里,已知的从节点有两个,分别是 IP 地址为172.19.0.4
和172.19.0.2
的节点。 -
sentinel known-sentinel
:这些配置项列出了已知的其他哨兵节点。在这里,已知的哨兵节点有两个,分别是 IP 地址为172.19.0.6
和172.19.0.5
的节点。 -
sentinel current-epoch
:这个配置项表示当前的纪元。纪元用于在哨兵节点之间协调故障转移。
总的来说,这些变化表明哨兵节点在启动后会自动发现主节点、从节点和其他哨兵节点的信息,并维护关于集群拓扑和配置的记录。这有助于哨兵节点共同协作来实现高可用性和故障切换。
请注意,这些配置信息是哨兵节点的内部状态,用于管理和维护Redis集群的稳定性和可用性。正常情况下,不需要手动修改这些配置项,哨兵节点会自动处理。
3.3.5 在分布式架构中,为什么设置多个哨兵节点
在 Redis 分布式架构中设置多个哨兵节点的主要目的是确保高可用性和故障容忍性。多个哨兵节点协同工作,监视主节点和从节点的状态,以及执行必要的故障切换操作。以下是为什么需要多个哨兵节点的一些关键原因:
-
故障检测和决策:多个哨兵节点可以相互协作,共同监视主节点和从节点的健康状态。如果有一个哨兵节点发现主节点或从节点宕机,它可以通知其他哨兵节点,共同决定是否执行故障切换。
-
避免单点故障:当只有一个哨兵节点时,它本身可能成为单点故障,一旦该哨兵节点宕机,整个故障检测和切换机制将受到影响。多个哨兵节点提供了冗余,即使其中一个哨兵节点宕机,其他哨兵节点仍然可以继续工作。
-
提高决策可靠性:多个哨兵节点的共同决策可以提高决策的可靠性。如果只有一个哨兵节点,它可能会因为各种原因而做出错误的故障切换决策,而多个哨兵节点需要达成共识,减少了误判的可能性。
-
负载分担:多个哨兵节点可以分担故障检测和决策的工作负载,提高了系统的性能和响应速度。
-
支持大规模集群:在大规模Redis集群中,故障检测和切换需要更多的资源和并发处理能力。多个哨兵节点可以协同工作,以满足高规模集群的要求。
-
容错性:如果一个哨兵节点本身出现问题,如网络问题或其他故障,其他哨兵节点可以继续工作,确保集群的正常运行。
总之,设置多个哨兵节点可以提高 Redis 分布式架构的可用性、可靠性和容错性。它们共同协作来监视、管理和维护 Redis 集群,确保主从切换等关键操作在发生故障时能够迅速而可靠地执行,从而保障应用程序的高可用性。
四、演示哨兵机制的主从自动切换
上文已经通过 Docker 建立了在哨兵监视下的 Redis 主从节点了,下面我将演示主节点崩溃后的主从节点的自动切换。
4.1 停止 Redis 主节点
要停止 Redis 主节点,可以使用命令:docker stop redis-master
:
停止之后可以使用 docker pa -a
查看所有的容器,包括停止的容器:
此时可以发现 redis-master
容器已经退出运行了。
4.2 重新选举的主节点
可以通过客户端连接 Redis 查看当前的主节点:
此时发现,主机的端口号 6380 对应的从节点,也就是 redis-slave1
成为了主节点。
如果再次启动刚才停止的 redis-master
节点:
可以发现该节点此时也成为了从节点。
4.3 查看哨兵节点日志
通过观察上述的日志记录可以发现:
当哨兵发现了主节点 redis-master
的状态变成了 sdown
,就进一步进行投票,当任务主节点党纪的总的投票数达到了总哨兵数的二分之一,则将该主节点的状态判定为 odown
,此时才确认主节点已经下线了。
- 主观下线(Subjectively Down,SDown):某个哨兵感知到主节点没心跳了,判定为主观下线。
- 客观下线(Objectively Down,ODown):多个哨兵达成⼀致意见,才能确定主节点下线。
4.4 领袖哨兵的选举原理
通过上面的日志可以发现:
哨兵redis-sentinel-1
首先为自己成为领袖投了一票:
其余两个哨兵,发现 redis-sentinel-1
已经投了它自己一票,因此也都把自己的票投给了 redis-sentinel-1
:
最后由于 redis-sentinel-1
的票数超过了总哨兵数的一半,因此成为了领袖节点。
因此,在Redis Sentinel中,领袖哨兵的选举原理可总结如下如下:
-
初始状态:当 Redis Sentinel 集群启动时,所有的哨兵节点都处于初始状态,没有领袖。
-
投票过程:每个哨兵节点都有权投票给自己成为领袖。在你提供的示例中,
redis-sentinel-1
首先为自己投了一票。 -
监测其他哨兵节点的投票:其他哨兵节点检测到
redis-sentinel-1
已经投了自己一票后,会将自己的票投给redis-sentinel-1
。这是因为在Redis Sentinel中,领袖哨兵需要得到超过一半的票数才能成为领袖。 -
投票数达到一半以上:当
redis-sentinel-1
的票数超过了哨兵节点总数的一半时,它就成为了领袖哨兵。 -
领袖选举完成:一旦
redis-sentinel-1
成为领袖哨兵,它将负责领导整个Redis Sentinel集群,并协调主节点和从节点的监控以及故障切换等操作。
总结来说,Redis Sentinel使用了一种基于投票的选举机制,哨兵节点在选举中投票给自己,然后其他哨兵节点检测到这一投票并将自己的票投给了同一哨兵,直到某一哨兵的票数超过了一半。这个哨兵将成为领袖,负责管理和维护整个Redis Sentinel集群。这种机制确保了领袖哨兵的选举是高度分布式和容错的,有助于维护Redis集群的高可用性。
4.5 新主节点的选举原理
通过上面的日志可以发现,新主节点的选取工作是由领袖节点来负责的:
在 Redis Sentinel 中,由领袖哨兵节点来负责执行新主节点的选举工作。这是因为领袖哨兵节点在整个Redis Sentinel集群中具有特殊的领导地位,负责协调和管理故障切换以及选举新的主节点。
-
主节点宕机:当主节点宕机或不可用时,所有的哨兵节点会检测到这一情况,并将主节点标记为下线。
-
哨兵节点投票:一旦主节点被标记为下线,哨兵节点会开始投票,选择新的主节点。通常情况下,领袖哨兵节点会起到协调的作用,但是实际选举过程中所有哨兵节点都有权投票。
-
选举条件:哨兵节点会考虑多个因素来选择新的主节点,包括从节点的优先级、复制偏移量、运行状态等。通常,从节点会成为新的主节点,但也可以根据配置和条件选择其他节点。
-
选举结果达成:一旦多数派的哨兵节点达成一致,选举结果就会生效。新的主节点被选出,并且哨兵节点会通知客户端和应用程序关于主节点的变化。
上述示例中,redis-sentinel-1
作为领袖哨兵节点起到了协调的作用,它和其他哨兵节点一起进行了选举过程,并最终选出了新的主节点。这种机制确保了Redis Sentinel集群的高可用性和可靠性,即使主节点宕机,也能够快速选举新的主节点来继续提供服务。
五、哨兵机制存在的缺陷
Redis Sentinel 是一个强大的工具,用于管理和监控 Redis 集群的高可用性和故障恢复。然而,它也存在一些缺陷和限制,包括:
-
复杂性:配置和管理Redis Sentinel本身可以变得复杂,特别是在大规模集群中。需要仔细考虑配置选项和监控策略。
-
单点故障:尽管Redis Sentinel 本身支持多个哨兵节点以提高可用性,但仍然存在哨兵节点本身可能成为单点故障的风险。如果领袖哨兵节点宕机,可能需要手动干预来恢复。
-
网络延迟和分区:Redis Sentinel 的工作依赖于网络通信,因此在网络延迟或分区的情况下,可能会导致错误的故障检测或切换决策。
-
故障切换时间:Redis Sentinel 可以快速检测主节点的故障,但故障切换过程中可能会有一些延迟,这可能会影响应用程序的可用性。
-
只支持单主节点:Redis Sentinel 主要用于单主节点的Redis集群,不直接支持多主节点的情况。如果需要管理多个主节点,需要额外的配置和管理。
-
监控有限:Redis Sentinel 提供了有限的监控和报警功能,不能满足所有监控需求。在生产环境中,可能需要集成其他监控工具来实现更全面的监控。
-
有限的自动化:虽然 Redis Sentinel 可以自动进行故障切换,但某些情况下可能需要手动干预,特别是在复杂的网络环境或集群配置中。
-
限制了某些Redis功能:使用 Redis Sentinel 可能会限制一些Redis功能,例如,某些命令只能在主节点上执行,而不能在从节点上执行。
尽管存在这些缺陷和限制,但 Redis Sentinel 仍然是一个可靠的工具,用于实现 Redis 集群的高可用性。对于大多数应用场景,它提供了足够的功能和可靠性,但在一些特殊情况下,可能需要考虑其他高可用性方案,如 Redis Cluster 或第三方工具。