Redis 集群模式与哨兵模式详解
Redis 是一个高性能的键值存储系统,广泛应用于缓存、消息队列等场景。为了提高 Redis 的可用性和扩展性,Redis 提供了两种主要的高可用方案:集群模式(Cluster Mode)和哨兵模式(Sentinel Mode)。本文将详细介绍这两种模式的工作原理、配置方法和使用示例。
1. Redis 哨兵模式(Sentinel Mode)
1.1 原理介绍
Redis Sentinel 是 Redis 的高可用性解决方案,它提供以下功能:
- 监控(Monitoring):Sentinel 会持续检查主服务器和从服务器是否正常运行
- 通知(Notification):当被监控的 Redis 实例出现问题时,Sentinel 可以通过 API 向管理员或其他应用程序发送通知
-
自动故障转移(Automatic failover):当主服务器不能正常工作时,Sentinel 会开始一次自动故障转移操作,将一个从服务器升级为新的主服务器,并让其他从服务器开始复制新的主服务器(哨兵会自动将恢复的原主节点降级为从节点,使其追随新选举的主节点
) - 配置提供者(Configuration provider):客户端连接 Sentinel 获取当前 Redis 主节点的地址
哨兵模式本质上是一个运行在特殊模式下的 Redis 进程,用于监控 Redis 主从结构中的各个实例。通常建议至少部署 3 个哨兵实例以确保高可用性。
1.2 哨兵模式工作原理
Redis Sentinel 的工作原理如下:
- 主节点监控:哨兵节点通过配置文件指定要监控的主节点,自动发现关联的从节点
- 多哨兵协作:多个哨兵节点协同工作,通过投票机制判断主节点是否失效
- 故障检测:当主节点在指定时间内没有回复PING,则认为它主观下线,多个哨兵确认后认定为客观下线
- 故障转移:从剩余的从节点中选举一个新的主节点,并更新其他从节点的复制目标
1.3 主从复制实现机制
Redis 主从复制是实现高可用的基础,其实现机制如下:
复制ID(replication ID)和偏移量(offset)验证:从库连接主库时会携带自己的replication ID和offset,主库通过比较这些信息判断是否需要进行全量同步,主库将自己的replid和offset发送给从库,使从库保存这些信息。
SYNC:全量同步,无论从节点之前是否同步过,每次都会重新生成RDB快照并传输全部数据
PSYNC:支持部分重同步,通过复制偏移量和备份ID判断,仅传输断线期间的增量数据
SYNC是Redis 2.8之前的旧机制
PSYNC从Redis 2.8开始引入,成为默认同步方式
1. 全量同步(同步):
- 从服务器向主服务器发送 SYNC/PSYNC 命令,请求同步数据。
- 主服务器收到命令后,开始执行 BGSAVE 命令,在后台生成一个 RDB 文件。
- 主服务器将生成的 RDB 文件发送给从服务器,在这个过程中,主服务器会将新的写命令缓存在内存中。
- 从服务器接收到 RDB 文件后,会清空自己的数据库,然后加载 RDB 文件到内存中。
- 主服务器将缓存的写命令发送给从服务器,从服务器执行这些命令,以保证数据的一致性。
在全量同步阶段,从服务器会等待主服务器发送 RDB 文件和缓存的写命令,这个过程是同步的,从服务器在加载 RDB 文件和执行缓存命令时,无法处理客户端的请求。
全量同步主要在以下情况下使用:
- 从服务器首次连接主服务器:当从服务器第一次建立与主服务器的连接时(建立长连接),必须进行全量同步以获取完整的数据副本
- 主从复制中断时间过长:当主从连接断开时间超过repl-backlog-size缓冲区容量时(即偏移量(offset)不在缓冲区),主服务器无法提供增量同步所需的数据,此时会触发全量同步
- 从服务器重启后数据不一致:如果从服务器重启后无法确定主服务器的复制进度,或者主从数据差异过大时,会触发全量同步
- 主服务器重启后:当主服务器重启后,如果从服务器无法识别主服务器的runid,也会触发全量同步
2. 增量同步(异步):
在全量同步完成后,主服务器会将新的写命令异步地发送给从服务器。主服务器会将写命令追加到自己的复制积压缓冲区中,并将这些命令发送给从服务器。从服务器接收到这些命令后,会异步地执行它们。
在增量同步阶段,主服务器不会等待从服务器的确认,就会继续处理新的写命令。因此,从服务器的数据可能会稍微落后于主服务器,但这种延迟通常是非常小的。
增量同步主要在以下情况下使用:
- 主从连接短暂中断后恢复:当网络问题导致主从连接短暂中断,且中断期间的数据变更仍在repl-backlog缓冲区中时(即偏移量(offset)在缓冲区),会使用增量同步
- 主从复制正常运行期间:在主从复制稳定运行期间,主服务器会持续将写命令通过增量方式同步给从服务器
- 从服务器重新连接主服务器:当从服务器重新连接主服务器时,如果主从数据差异较小且repl-backlog缓冲区未覆盖相关数据,会使用增量同步
3. 心跳检测:
- 主从节点通过心跳机制维持连接
- 定期发送 ping/pong 消息检测连接状态
1.4 配置示例
主节点配置
# 监听端口
port 6379
# 设置密码认证
requirepass your_master_password
# 连接主节点时的密码(用于主从复制)
masterauth your_master_password
# 允许所有IP连接(生产环境建议指定具体IP)
bind 0.0.0.0
# 后台运行
daemonize yes
从节点配置
# 监听端口
port 6380
# 指定主节点地址和端口(主从复制配置)
slaveof 127.0.0.1 6379
# 连接主节点时使用的密码
masterauth your_master_password
# 从节点密码
requirepass your_slave_password
# 允许所有IP连接
bind 0.0.0.0
# 后台运行
daemonize yes
哨兵配置
# 哨兵监听端口
port 26379
# 监控的主节点名称、IP、端口和法定人数
# 格式:sentinel monitor <mastername> <ip> <port> <quorum>
sentinel monitor mymaster 127.0.0.1 6379 2
# 主节点密码认证
sentinel auth-pass mymaster your_master_password
# 判断主节点主观下线的毫秒数
sentinel down-after-milliseconds mymaster 5000
# 故障转移时,同时进行复制的从节点数量
sentinel parallel-syncs mymaster 1
# 故障转移超时时间(毫秒)
sentinel failover-timeout mymaster 10000
# 允许所有IP连接
bind 0.0.0.0
# 后台运行
daemonize yes
1.5 Spring Boot 配置
spring:
redis:
# 哨兵模式配置
sentinel:
# 主节点名称
master: mymaster
# 哨兵节点列表
nodes:
- 127.0.0.1:26379
- 127.0.0.1:26380
- 127.0.0.1:26381
# Redis密码
password: your_master_password
# 连接超时时间
timeout: 2000ms
# 数据库索引(默认0)
database: 0
2. Redis 集群模式(Cluster Mode)
2.1 原理介绍
Redis Cluster 是 Redis 的分布式解决方案,它具备以下特点:
- 数据分片:数据自动分片到多个节点上,每个节点负责一部分哈希槽(hash slot)
- 高可用性:每个主节点可以有多个从节点,实现主从复制和故障转移
- 去中心化:集群中的每个节点都保存着整个集群的状态信息
- 客户端路由:客户端可以连接任意节点,节点会将请求重定向到正确的节点
2.2 为什么集群模式不需要哨兵
Redis Cluster 与哨兵模式相比,具有以下关键差异,因此不需要额外的哨兵组件:
-
内置高可用性:
- Redis Cluster 本身已经内置了故障检测和自动故障转移机制
- 每个节点都参与集群状态的维护和故障检测
- 不需要外部组件来监控节点状态
-
去中心化架构:
- 集群中的每个节点都保存完整的集群状态信息
- 节点之间通过 Gossip 协议交换状态信息
- 没有单点故障问题
-
自动主从管理:
- 集群在创建时就配置了主从关系
- 当主节点失效时,相关从节点会自动进行故障转移
- 整个过程由集群内部协议处理,无需外部干预
-
分布式决策:
- 故障检测和主从切换由集群内多数节点共同决定
- 避免了哨兵模式中可能出现的网络分区问题
2.3 自动分配主从节点机制
Redis Cluster 在创建时会自动分配主从节点关系:
-
节点角色分配:
- 在创建集群时,通过
--cluster-replicas参数指定每个主节点的从节点数量 - 系统自动将节点分为主节点和从节点
- 在创建集群时,通过
-
槽位分配:
- 16384 个哈希槽被均匀分配给主节点
- 每个从节点知道自己对应的主节点
-
故障转移机制:
- 当主节点失效时,其从节点会通过选举产生新的主节点
- 其他从节点会更新复制目标到新的主节点
2.4 数据分片机制
Redis Cluster 采用哈希槽机制实现数据分片:
- 哈希槽划分:整个集群被划分为 16384 个哈希槽(0-16383)
- 键到槽映射:每个 key 通过 CRC16 算法计算哈希值,然后对 16384 取模得到槽位号
slot = CRC16(key) % 16384
-
槽位分配:这些槽位会均匀分布在不同的主节点上
示例分配:
3主节点:约5461槽/节点(如0-5460,5461-10921,10922-16383)
4主节点:4096槽/节点
5主节点:3276槽/节点(余4槽分配给前4节点)
Hash Tag 机制
当 key 包含 { 和 } 时,只有花括号内的部分会被用于哈希计算,这称为 hash tag 机制:
-
user:1000:profile和user:1000:settings会映射到不同槽位 -
{user:1000}:profile和{user:1000}:settings会映射到相同槽位
这样可以保证相关数据存储在同一节点上,支持多键操作。
2.5 集群模式工作原理
Redis Cluster 的工作原理如下:
- 节点发现:通过 MEET 消息发现新节点
- 槽位分配:通过 CLUSTER ADDSLOTS 命令分配槽位
- 状态同步:节点间通过 Gossip 协议交换集群状态(IP、端口、运行ID、槽位信息),所有节点(包括主节点和从节点)都会参与Gossip协议。
- 请求路由:节点收到请求后,如果槽位不属于自己,则返回MOVED重定向
- 故障检测:通过PING/PONG消息检测节点状态
- 故障转移:从节点检测到主节点失效后发起选举,成为新的主节点
2.6 配置示例
节点配置
# 节点监听端口
port 7000
# 开启集群模式
cluster-enabled yes
# 集群配置文件(自动生成和维护)
cluster-config-file nodes-7000.conf
# 节点间通信超时时间(毫秒)
cluster-node-timeout 15000
# 节点间是否允许执行故障转移
cluster-slave-no-failover no
# 是否要求所有槽位都被覆盖才提供服务
cluster-require-full-coverage no
# 设置密码认证
requirepass your_cluster_password
# 连接主节点时的密码(用于主从复制)
masterauth your_cluster_password
# 允许所有IP连接
bind 0.0.0.0
# 后台运行
daemonize yes
2.7 创建集群
# 创建集群(3主3从,每个主节点1个从节点)
redis-cli --cluster create 127.0.0.1:7000 127.0.0.1:7001 127.0.0.1:7002 127.0.0.1:7003 127.0.0.1:7004 127.0.0.1:7005 --cluster-replicas 1
2.8 Spring Boot 配置
spring:
redis:
# 集群模式配置
cluster:
# 集群节点地址列表
nodes:
- 127.0.0.1:7000
- 127.0.0.1:7001
- 127.0.0.1:7002
- 127.0.0.1:7003
- 127.0.0.1:7004
- 127.0.0.1:7005
# 最大重定向次数
max-redirects: 3
# Redis密码
password: your_cluster_password
# 连接超时时间
timeout: 2000ms
3. 两种模式对比
| 特性 | 哨兵模式 | 集群模式 |
|---|---|---|
| 数据分片 | 不支持 | 支持(16384个哈希槽) |
| 扩展性 | 垂直扩展 | 水平扩展 |
| 高可用 | 需要哨兵实现 | 内置高可用机制 |
| 主从管理 | 哨兵自动管理 | 集群自动管理 |
| 客户端复杂度 | 简单 | 需要支持集群协议 |
| 多键操作 | 支持 | 仅支持同一槽位 |
| 事务支持 | 完全支持 | 仅支持同一节点 |
| 最小节点数 | 1主1从+3哨兵=5个 | 3主3从=6个 |
| 适用场景 | 数据量小,需要高可用 | 数据量大,需要分片 |
4. 总结
Redis 的哨兵模式和集群模式都是为了解决高可用性问题而设计的,但它们适用于不同的场景:
哨兵模式适用于数据量不大,但需要高可用性的场景。它通过监控和自动故障转移来保证服务的连续性,需要额外的哨兵组件来实现高可用。
集群模式适用于数据量大,需要水平扩展的场景。它不仅提供了高可用性,还通过数据分片实现了水平扩展。集群模式内置了高可用机制,不需要额外的哨兵组件,主从节点关系在创建时自动分配和管理。
Redis哨兵模式和集群模式在主从复制的基本机制上是相似的,都基于相同的复制原理和同步协议,都使用PSYNC/PSYNC2协议,都支持全量和增量同步,都通过主从复制实现数据冗余
选择哪种模式主要取决于数据量大小、性能要求和系统复杂度等因素。集群模式因为其内置的高可用性和自动主从管理机制,更适合现代分布式应用的需求。