Redis 作为一款高性能的键值对存储系统, 在缓存、数据库等场景中被广泛应用。然而, 在传统的主从复制架构中, 仍然存在一些问题, 特别是在主节点故障时的处理上。为了解决这些问题,Redis 引入了哨兵机制, 本文将详细介绍 Redis 哨兵机制的概念、工作原理以及如何搭建一个哨兵系统。
1. 哨兵机制的由来
在传统的 Redis 主从复制架构中, 主要存在两个问题:
- 主节点故障时, 需要手动进行主备切换, 这个过程复杂且需要人工参与, 无法保证故障恢复的时效性。
- 虽然主节点可以将读压力分散到从节点, 但写压力和存储压力仍然集中在主节点, 受到单机性能的限制。
哨兵机制主要解决了第一个问题, 即高可用性问题。它能够在主节点故障时自动完成故障发现和故障转移, 并通知应用程序, 从而实现真正的高可用。
2. 哨兵机制概述
Redis 的哨兵机制是一个分布式系统, 包含多个哨兵节点和 Redis 数据节点。每个哨兵节点会监控数据节点和其他哨兵节点。当发现节点不可达时, 哨兵会对该节点进行下线标识。如果下线的是主节点, 哨兵们会进行"协商", 当大多数哨兵对主节点不可达达成共识后, 它们会选举出一个领导者来完成自动故障转移, 并实时通知 Redis 客户端。整个过程是完全自动的, 无需人工干预。
3. 搭建哨兵系统
接下来, 我们将使用 Docker 来搭建一个 Redis 哨兵环境, 包括 3 个数据节点 (1 主 2 从) 和 3 个哨兵节点。
3.1 搭建数据节点
首先, 我们需要创建一个 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
这个配置文件定义了三个服务: 一个主节点和两个从节点。每个节点都使用 Redis 5.0.9 镜像, 并启用了 AOF 持久化。从节点通过--slaveof
参数指定了主节点的地址和端口。
使用以下命令启动数据节点:
sudo docker-compose up -d
3.2 搭建哨兵节点
接下来, 我们需要为哨兵节点创建配置文件。在 redis-sentinel
目录中创建三个相同内容的配置文件 (sentinel1.conf
, sentinel2.conf
, sentinel3.conf
):
bind 0.0.0.0
port 26379
sentinel monitor redis-master redis-master 6379 2
sentinel down-after-milliseconds redis-master 1000
这个配置指定了哨兵监听的主节点信息, 以及判断主节点失效的条件。
然后, 创建另一个 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
networks:
default:
external:
name: redis-data_default
使用以下命令启动哨兵节点:
sudo docker-compose up -d
4. 哨兵机制的工作原理
哨兵机制的工作流程主要包括以下几个步骤:
4.1 主观下线
当主节点宕机时, 与主节点和哨兵之间的心跳包通信中断。此时, 每个哨兵节点会将主节点标记为主观下线 (Subjective Down, SDown), 并投票表示故障。
4.2 客观下线
当故障得票数达到或超过配置的法定票数时, 主节点被认定为客观下线 (Objective Down, ODown) 。
4.3 选举哨兵 leader
为了协调选举新主节点的工作, 哨兵节点们需要先选出一个 leader 。这个过程使用了 Raft 算法:
- 每个哨兵节点向其他所有哨兵节点发起"拉票请求"。
- 收到请求的节点会回复"投票响应", 可能投票或不投票。
- 如果某个哨兵获得超过半数的票, 它就成为 leader 。
4.4 选举新主节点
leader 哨兵负责从从节点中选择一个作为新的主节点。选择标准如下:
- 优先级高 (配置项 slave-priority 或 replica-priority 值小) 的优先。
- 复制偏移量 (replication offset) 大的优先。
- 运行 ID(run id) 小的优先。
4.5 故障转移
选出新主节点后,leader 哨兵会执行以下操作:
- 向选中的从节点发送
SLAVEOF NO ONE
命令, 使其成为新主节点。 - 向其他从节点发送
SLAVEOF
命令, 使它们连接到新主节点。 - 更新客户端配置, 将写操作转向新主节点。
5. 哨兵机制的注意事项
- 哨兵节点不应只有一个, 否则哨兵节点故障会影响整个系统的可用性。
- 哨兵节点数量最好是奇数, 便于 leader 选举。
- 哨兵节点不存储数据, 数据存储仍由 Redis 主从节点负责。
- 哨兵机制解决了高可用性问题, 但不能解决数据丢失或存储容量受限的问题。
- 当数据量接近或超过机器物理内存时, 可能需要考虑使用 Redis 集群来扩展存储容量。
6. 结论
Redis 哨兵机制是一个强大的工具, 能够大大提高 Redis 系统的可用性。通过自动故障检测和故障转移, 它降低了系统维护的复杂度, 减少了人工干预的需求。然而, 在使用哨兵机制时, 我们也需要注意它的局限性, 并根据实际需求选择合适的 Redis 架构方案。
参考文献
- [Redis] 哨兵机制-CSDN 博客. https://blog.csdn.net/a_zhee1/article/details/140165865