【Redis合集-02】保姆级教程!Redis 哨兵 + 集群 Linux 部署全流程,一步到位
目录
7.2 Spring Boot 连接配置(Lettuce / Jedis)
6.2 为什么要指定 --cluster-replicas 1
哨兵(Sentinel)模式
一、哨兵模式概述
1.1 主从架构的痛点回顾
我们搭建了主从复制架构,解决了读扩展和数据备份问题,但存在一个致命缺陷:
主节点宕机后,必须人工干预:手动将一个从节点提升为主节点,修改其他从节点指向新主节点,并通知应用方切换连接地址。
这种手动操作在生产环境中完全不可接受,原因有如下三点:
-
响应时间长:人工发现故障 + 操作耗时,服务中断窗口大
-
操作风险高:手忙脚乱容易误操作,导致数据丢失
-
无法夜间值守:凌晨宕机只能等上班处理
1.2 哨兵是什么
Redis Sentinel(哨兵) 是 Redis 官方提供的 高可用解决方案,核心能力总结:
哨兵是一个独立的进程,持续监控主从节点的健康状态,在主节点故障时自动将一个从节点提升为新主节点,并通知客户端切换连接。
1.3 哨兵的核心能力
| 能力 | 说明 |
|---|---|
| 监控(Monitoring) | 定期检查主节点、从节点是否正常运行 |
| 自动故障转移(Automatic Failover) | 主节点不可用时,自动选举从节点升级为主节点 |
| 通知(Notification) | 将故障转移结果通知给客户端 |
| 配置提供者(Configuration Provider) | 客户端通过哨兵获取当前主节点地址 |
关键理解:哨兵本身不存储业务数据,它只是监控和控制角色。数据读写仍然走 Redis 主从节点。
二、哨兵架构与工作原理
2.1 为什么需要多个哨兵
单哨兵存在严重问题:
-
哨兵本身宕机,整个监控体系瘫痪
-
网络波动可能导致哨兵误判主节点下线
-
单哨兵的判断不具备权威性
因此,生产环境必须部署哨兵集群,至少 3 个哨兵节点(奇数个)。
2.2 哨兵集群架构图
一般部署到不同的机器上

2.3 主观下线(SDOWN)与客观下线(ODOWN)
这是哨兵最核心的两个判断概念,必须理解透彻:
| 概念 | 英文 | 定义 | 触发条件 |
|---|---|---|---|
| 主观下线 | SDOWN | 单个哨兵认为节点不可达 | 哨兵 PING 节点超时,超过 down-after-milliseconds |
| 客观下线 | ODOWN | 多数哨兵都认为主节点不可达 | 超过 quorum 数量的哨兵都报告 SDOWN |
核心逻辑:SDOWN 是单点判断,可能是网络波动误判;ODOWN 是集群共识,触发故障转移的前提。
流程示例:
Sentinel-1: "Master 不响应,我判断 SDOWN" ─┐
Sentinel-2: "Master 不响应,我判断 SDOWN" ─┼─→ quorum=2,达成 ODOWN
Sentinel-3: "Master 正常,无 SDOWN" ─┘ 忽略少数意见
│
启动故障转移流程
2.4 故障转移完整流程
-
多个哨兵发现主节点不可达,标记为 SDOWN
-
SDOWN 数量达到
quorum,确认 ODOWN -
哨兵集群进行 领导者选举(Raft 算法变体),选出执行故障转移的哨兵
-
领导者哨兵在存活的从节点中 选举最优从节点 作为新主节点
-
将选中的从节点 执行 slaveof no one,升级为主节点
-
通知其余从节点 重新 slaveof 到新主节点
-
将故障的原主节点降为从节点(待其恢复后自动加入)
-
通知客户端 主节点地址已变更
2.5 从节点选举优先级规则
领导者哨兵依据以下规则从所有从节点中选出最优的一个:
| 优先级 | 规则 | 说明 |
|---|---|---|
| 1 | slave-priority 最小 | 手动配置的优先级,数字越小优先级越高 |
| 2 | 复制偏移量最大 | 数据最新,丢失数据最少 |
| 3 | runid 字典序最小 | 前两者相同时,runid 最小的胜出(确定性保证) |
实践建议:对不同性能的从节点设置不同的 slave-priority,例如:
-
性能好的从节点:
slave-priority 10 -
性能差的从节点:
slave-priority 50
这样故障转移时会优先选性能好的节点作为新主节点。
三、实验环境规划
| 角色 | IP 地址 | 端口 | 说明 |
|---|---|---|---|
| Master | 192.168.10.100 | 6379 | Redis 主节点 |
| Slave1 | 192.168.10.101 | 6379 | Redis 从节点 |
| Slave2 | 192.168.10.102 | 6379 | Redis 从节点 |
| Sentinel-1 | 192.168.10.100 | 26379 | 哨兵节点1 |
| Sentinel-2 | 192.168.10.101 | 26379 | 哨兵节点2 |
| Sentinel-3 | 192.168.10.102 | 26379 | 哨兵节点3 |
注意:
哨兵可以和 Redis 节点部署在同一台机器上,端口不同即可(Redis 6379,Sentinel 26379)
生产环境建议哨兵至少 3 台独立机器,避免单机故障同时带走 Redis 和哨兵
四、哨兵模式搭建步骤
4.1 前提:已完成主从架构
确保三台机器的 Redis 主从复制已正常运行:
# 在主节点验证
redis-cli -h 192.168.10.100 -p 6379 info replication
# 应看到 role:master,connected_slaves:2
4.2 哨兵配置文件
在每台机器上创建哨兵配置文件 /usr/local/redis/conf/sentinel.conf
# 哨兵监听端口
port 26379
# 后台运行
daemonize yes
# 日志文件
logfile "/usr/local/redis/logs/sentinel.log"
# 工作目录
dir /usr/local/redis/data
# ========== 核心:监控主节点配置 ==========
# 格式:sentinel monitor <master-name> <ip> <port> <quorum>
sentinel monitor mymaster 192.168.10.100 6379 2
# 主观下线判定时间(毫秒)
sentinel down-after-milliseconds mymaster 30000
# 故障转移超时时间(毫秒)
sentinel failover-timeout mymaster 180000
# 同时向新主节点同步的从节点数量
sentinel parallel-syncs mymaster 1
# 如果主节点有密码,需要配置
# sentinel auth-pass mymaster your_password
4.3 核心参数详解
| 参数 | 含义 | 推荐值 | 解释 |
|---|---|---|---|
sentinel monitor |
监控的主节点别名、IP、端口、法定票数 | mymaster 192.168.10.100 6379 2 |
quorum=2:至少2个哨兵同意才触发故障转移 |
down-after-milliseconds |
主观下线超时时间 | 30000(30秒) |
哨兵 PING 超过此时间无响应,判定 SDOWN。不要设太短,避免网络波动误判 |
failover-timeout |
故障转移总超时 | 180000(3分钟) |
转移超过此时间视为失败,重新选举领导者 |
parallel-syncs |
并行同步的从节点数 | 1 |
新主节点同时向多少个从节点同步数据。越小越稳,越大越快 |
quorum 的设定原则:
quorum 值 建议设为节点总数的 (N/2)+1(即多数派)
例如 3 个哨兵,quorum=2;5 个哨兵,quorum=3
注意区分:quorum 是确认 ODOWN 的票数,不是选领导者的票数。选领导者需要 半数以上(majority)
4.4 启动哨兵
在三台机器上分别执行:
# 启动哨兵(两种命令等价)
redis-sentinel /usr/local/redis/conf/sentinel.conf
# 或者
redis-server /usr/local/redis/conf/sentinel.conf --sentinel
检查哨兵进程:
ps -ef | grep sentinel
五、哨兵状态验证
5.1 连接哨兵查看信息
redis-cli -h 192.168.10.100 -p 26379
进入哨兵命令行后,执行以下命令:
查看主节点信息
> sentinel master mymaster
重要输出字段:
"name" : "mymaster"
"ip" : "192.168.10.100"
"port" : "6379"
"flags" : "master" # 主节点状态
"num-slaves" : "2" # 从节点数量
"num-other-sentinels" : "2" # 其他哨兵数量
"quorum" : "2" # 法定票数
查看从节点列表
> sentinel slaves mymaster
查看哨兵集群成员
> sentinel sentinels mymaster
重点确认:三个哨兵互相发现,
num-other-sentinels值为 2。
5.2 观察哨兵日志
tail -f /usr/local/redis/logs/sentinel.log
正常日志中能看到哨兵监控的主从节点信息,以及哨兵之间的互相发现过程。
六、故障转移实战验证
6.1 模拟主节点宕机
在 Master 机器上执行:
# 方式一:直接 kill
redis-cli -h 192.168.10.100 -p 6379 shutdown
# 方式二:强制杀进程(更真实模拟宕机)
kill -9 $(pgrep redis-server)
6.2 观察哨兵日志
在任意哨兵节点持续观察日志:
tail -f /usr/local/redis/logs/sentinel.log
能看到完整的故障转移过程:
# 1. 主观下线检测
+sdown master mymaster 192.168.10.100 6379
# 2. 客观下线达成
+odown master mymaster 192.168.10.100 6379 #quorum 2/2
# 3. 选举新领导者哨兵
+vote-for-leader xxxxxx ...
# 4. 选举新主节点
+selected-slave slave 192.168.10.101:6379 ...
# 5. 从节点升级为主
+switch-master mymaster 192.168.10.100 6379 192.168.10.101 6379
# 6. 通知其余从节点
+slave slave 192.168.10.102:6379 ... master 192.168.10.101 6379
# 7. 原主节点降为从节点
+slave slave 192.168.10.100:6379 ... master 192.168.10.101 6379
6.3 验证新主节点
redis-cli -h 192.168.10.101 -p 6379 info replication
预期输出:
role:master # Slave1 已成为主节点 connected_slaves:1 # Slave2 已重新挂载到新主节点
6.4 原主节点恢复后
重新启动原来的主节点(192.168.10.100):
redis-server /usr/local/redis/conf/redis.conf
再次查看复制状态,它会自动以从节点身份加入,挂载到新主节点下:
redis-cli -h 192.168.10.100 -p 6379 info replication
# role:slave
# master_host:192.168.10.101
整个过程无需任何人工干预,实现了真正的自动故障转移。
七、Java 客户端连接哨兵
这是哨兵模式最关键的 使用环节,应用如何连接哨兵并自动切换主节点:
7.1 Jedis 连接示例
// 哨兵节点集合
Set<String> sentinels = new HashSet<>();
sentinels.add("192.168.10.100:26379");
sentinels.add("192.168.10.101:26379");
sentinels.add("192.168.10.102:26379");
// 连接池配置
JedisPoolConfig poolConfig = new JedisPoolConfig();
poolConfig.setMaxTotal(10);
poolConfig.setMaxIdle(5);
// 创建哨兵连接池
JedisSentinelPool sentinelPool = new JedisSentinelPool(
"mymaster", // 主节点别名,和哨兵配置中的一致
sentinels, // 哨兵节点集合
poolConfig,
"your_password" // 如果设置了密码
);
// 获取连接(哨兵自动路由到当前主节点)
try (Jedis jedis = sentinelPool.getResource()) {
jedis.set("key", "value");
String value = jedis.get("key");
}
7.2 Spring Boot 连接配置(Lettuce / Jedis)
spring:
redis:
password: your_password
sentinel:
master: mymaster # 哨兵配置中的主节点别名
nodes: # 所有哨兵节点地址
- 192.168.10.100:26379
- 192.168.10.101:26379
- 192.168.10.102:26379
lettuce:
pool:
max-active: 10
max-idle: 5
关键点:客户端不需要知道主节点具体是哪个 IP,哨兵会自动告知当前主节点地址,主从切换后客户端自动感知并重连。
八、哨兵模式的局限性
哨兵解决了自动故障转移,但仍有两个短板:
| 局限 | 说明 | 解决方向 |
|---|---|---|
| 写压力仍集中 | 所有写请求依然走单个主节点 | Redis Cluster 分片集群 |
| 内存容量受限 | 单机内存上限,数据无法水平拆分 | Redis Cluster 数据分片 |
| 数据丢失风险 | 异步复制,故障切换可能丢失少量数据 | 配置 min-slaves-to-write 和持久化策略 |
| 脑裂风险 | 网络分区可能产生双主节点 | 合理配置 quorum 和 min-slaves |
min-slaves-to-write 配置详解
一、配置定义
min-slaves-to-write(Redis 5.0+ 改名为 min-replicas-to-write)是 Redis 主节点 上的一个安全配置参数,含义如下:
主节点在执行写命令之前,检查当前存活的从节点数量。如果在线从节点数少于该值,主节点将拒绝写入请求并返回错误。
二、配置语法
# redis.conf 中的配置
min-replicas-to-write <数量>
min-replicas-max-lag <秒数>
这两个参数必须配对使用,缺一不可。
| 参数 | 含义 |
|---|---|
min-replicas-to-write |
至少需要多少个从节点在线,才允许写入 |
min-replicas-max-lag |
从节点延迟超过这个秒数,视为 不在线 |
三、工作原理
判断逻辑:
正常在线的从节点数量 = 从节点总数 - 延迟超过 min-replicas-max-lag 的从节点 如果 正常在线从节点数 < min-replicas-to-write → 拒绝所有写入,返回错误 否则 → 正常接受写入
流程图解:
客户端写入请求
│
▼
┌─────────────────────────┐
│ 检查在线从节点数量 │
│ (延迟 < max-lag 的从节点)│
└───────────┬─────────────┘
│
在线数 >= min?
│ │
是 否
│ │
▼ ▼
✅ 允许写入 ❌ 拒绝写入
NOREPLICAS
Not enough good
replicas to write.
四、这个配置解决什么问题
核心场景:防止主从异步复制导致的数据丢失。
在主从异步复制架构中,存在这样一个风险流程:
1. 主节点写入一条数据
2. 还没来得及同步到从节点
3. 主节点宕机
4. 哨兵将某个从节点提升为新主节点
5. → 刚才写入的那条数据永久丢失
如果设置 min-replicas-to-write 1,流程变为:
1. 客户端写入请求到达主节点
2. 主节点检查:至少 1 个从节点在线且延迟 < max-lag
3. 条件满足,写入成功
4. 即使主节点立刻宕机,数据也已同步到至少一个从节点
5. 哨兵选主时,数据已存在的从节点会被优先选中(offset 更大)
→ 数据丢失概率大幅降低
本质:通过牺牲写入可用性(有从节点掉线时拒绝写入),换取数据一致性(保证写入的数据至少存在于一个从节点)。
五、生产环境配置建议
| 场景 | 推荐配置 | 说明 |
|---|---|---|
| 低安全要求 | 不配置(默认0) | 允许任何情况写入,可能丢失数据 |
| 一般安全 | min-replicas-to-write 1 |
至少一个从节点在线才允许写 |
| 高安全要求 | min-replicas-to-write 2 |
至少两个从节点在线才允许写 |
六、与哨兵的配合
在哨兵架构中,这两个配置尤为重要:
# redis.conf(主节点配置)
min-replicas-to-write 1
min-replicas-max-lag 10
# sentinel.conf(哨兵配置)
sentinel monitor mymaster 192.168.10.100 6379 2
sentinel down-after-milliseconds mymaster 30000
协同效果:
-
主节点角度:没有健康的从节点,拒绝写入(保数据不丢)
-
哨兵角度:主节点失联 30 秒,触发故障转移(保服务可用)
-
两者配合,数据安全 + 服务可用 兼顾
七、注意事项
-
不适合所有业务:对写入可用性要求极高的场景(如实时性日志、临时缓存),这个配置可能导致写入失败,需谨慎评估
-
必须两个参数同时设置:只设
min-replicas-to-write不设min-replicas-max-lag无效 -
动态调整:可通过
CONFIG SET在线修改,无需重启 -
建议写入配置文件:重启后生效,避免动态修改后忘记持久化
redis-cli> CONFIG SET min-replicas-to-write 1
redis-cli> CONFIG SET min-replicas-max-lag 10
min-replicas-to-write是 Redis 主节点上的"安全阀"——从节点掉线太多时宁可拒绝写入,也不冒险丢失数据。配合哨兵的自动故障转移,能有效降低异步复制架构下的数据丢失风险。
九、生产环境部署建议
9.1 哨兵节点数量
-
至少 3 个,且必须是 奇数个(3、5、7)
-
推荐 3 个 起步,大规模集群可用 5 个
9.2 哨兵部署位置
-
哨兵应部署在 独立的物理机或虚拟机 上
-
避免与 Redis 节点同机部署(虽然可以,但不推荐)
-
哨兵之间网络延迟应低于 100ms
9.3 防火墙端口
哨兵端口 26379 也需要放行:
firewall-cmd --permanent --add-port=26379/tcp
firewall-cmd --reload
9.4 推荐配置汇总
# sentinel.conf 推荐配置
port 26379
daemonize yes
logfile "/usr/local/redis/logs/sentinel.log"
dir /usr/local/redis/data
sentinel monitor mymaster 192.168.10.100 6379 2
sentinel down-after-milliseconds mymaster 30000
sentinel failover-timeout mymaster 180000
sentinel parallel-syncs mymaster 1
# 安全相关
# sentinel auth-pass mymaster your_strong_password
十、总结
梳理了 Redis Sentinel 哨兵模式 的原理与部署:
-
哨兵不是存储层,而是独立的监控与控制进程
-
SDOWN → ODOWN → 领导者选举 → 从节点选举 → 自动切换 是完整故障转移链路
-
quorum 确认 ODOWN,majority 选领导者,两者含义不同
-
客户端通过 哨兵发现主节点,切换后自动感知,无需人工改配置
-
哨兵模式解决了 高可用,但写压力和内存容量问题留给 Cluster 解决
集群模式
一、Cluster 集群概述
1.1 前三大架构的演进回顾
| 架构 | 解决的问题 | 遗留缺陷 |
|---|---|---|
| 单机版 | 基本缓存需求 | 单点故障、读写压力集中、内存上限 |
| 主从复制 | 读扩展 + 数据备份 | 写压力仍在主节点、故障转移需手动 |
| 哨兵模式 | 自动故障转移 | 写压力仍集中、数据无法水平拆分、内存受单机限制 |
核心矛盾:哨兵解决了高可用,但数据量超出单机内存时,垂直扩展(加内存)成本高昂且存在物理上限。Redis Cluster 正是为解决水平扩展而生。
1.2 什么是 Redis Cluster
Redis Cluster 是 Redis 官方提供的 分布式集群解决方案,核心特征:
将数据自动切分(分片)到多个 Redis 节点上,每个节点只存储整体数据集的一部分,突破单机内存限制,同时支持自动故障转移
1.3 Cluster 核心能力
| 能力 | 说明 |
|---|---|
| 数据分片 | 数据分散存储在多个主节点,突破单机内存瓶颈 |
| 自动故障转移 | 主节点宕机,其从节点自动晋升为主(无需外部哨兵) |
| 去中心化架构 | 无中心代理节点,客户端可直连任意集群节点 |
| 线性扩展 | 增加节点即可扩大内存和吞吐量 |
关键理解:Redis Cluster 自带哨兵能力,不再需要单独部署 Sentinel。集群内部通过 Gossip 协议互相通信,完成节点发现、故障检测、故障转移。
二、数据分片原理(核心机制)
2.1 虚拟哈希槽(Hash Slot)
Redis Cluster 没有使用一致性哈希,而是采用 虚拟哈希槽(Hash Slot) 方案,这是理解集群的第一把钥匙。
基本规则:
-
整个集群固定划分为 16384 个哈希槽(0 ~ 16383)
-
每个主节点负责管理一部分哈希槽
-
对每个 Key 进行 CRC16 校验,然后对 16384 取模,决定 Key 属于哪个槽
槽位计算公式:slot = CRC16(key) % 16384

2.2 为什么是 16384 个槽
| 原因 | 说明 |
|---|---|
| 心跳包体积 | 节点间通过 Gossip 协议同步槽位信息,槽位位图大小 = 16384/8 = 2KB,传输效率高 |
| 网络开销 | 16384 足够均匀分布,不会因槽位数过多导致心跳包过大(如 65536 需要 8KB) |
| 节点数适配 | 集群最大支持 1000 个主节点,16384 个槽分配完全够用 |
2.3 为什么不用一致性哈希
| 对比维度 | 一致性哈希 | Redis 哈希槽 |
|---|---|---|
| 数据迁移 | 加减节点时影响相邻节点 | 槽可以在节点间 灵活迁移 |
| 负载均衡 | 虚拟节点增多才趋于均衡 | 槽粒度固定,天然均衡 |
| 实现复杂度 | 需维护哈希环 | 槽映射表简单清晰 |
| 节点扩容 | 可能数据倾斜 | 手动迁移指定槽即可 |
核心优势:哈希槽让数据迁移变得可控——哪个槽归属哪个节点是明确可调的,运维友好。
三、Cluster 架构设计
3.1 典型架构:三主三从
生产环境最低推荐配置:3 个主节点 + 3 个从节点(跨机器部署)
-
主节点(Master):负责指定槽位的读写操作
-
从节点(Slave):复制主节点数据,主节点故障时晋升
-
交叉部署:Master1 的从节点不要和 Master1 在同一台物理机上,避免物理机宕机导致主从同时丢失
3.2 Gossip 协议
节点间通过 Gossip(流言)协议 持续交换信息:
每隔一段时间,每个节点随机选择几个其他节点:
├─ PING:携带自己已知的节点信息、槽位分配
├─ PONG:回复收到消息,并携带自己的信息
└─ 通过不断交换,最终所有节点状态达成一致
Gossip 协议使得集群去中心化,没有单点故障。
四、实验环境规划
| 角色 | IP 地址 | 端口 | 说明 |
|---|---|---|---|
| Master1 | 192.168.10.11 | 7001 | 主节点1,负责槽 0-5460 |
| Master2 | 192.168.10.12 | 7002 | 主节点2,负责槽 5461-10922 |
| Master3 | 192.168.10.13 | 7003 | 主节点3,负责槽 10923-16383 |
| Slave1 | 192.168.10.14 | 7004 | 从节点1,复制 Master1 |
| Slave2 | 192.168.10.15 | 7005 | 从节点2,复制 Master2 |
| Slave3 | 192.168.10.16 | 7006 | 从节点3,复制 Master3 |
说明:演示环境端口从 7001 开始递增,实际生产可根据机器规划灵活设定。每个节点各自独立部署。
五、Cluster 集群搭建步骤
5.1 前提准备
每台机器需要完成单机版 Redis 安装,安装路径统一为 /usr/local/redis。
在每个节点上创建对应的目录和配置文件
# 以 Master1(7001)为例,其他节点类比修改
mkdir -p /usr/local/redis/cluster/7001/{conf,logs,data}
5.2 单节点配置文件
创建 /usr/local/redis/cluster/7001/conf/redis.conf,内容如下:
# ========== 基础配置 ==========
port 7001 # 端口号,每个节点各不相同
daemonize yes # 后台守护进程运行
bind 0.0.0.0 # 绑定所有网卡,允许外部连接
protected-mode no # 关闭保护模式
# ========== 日志与数据目录 ==========
logfile "/usr/local/redis/cluster/7001/logs/redis.log"
dir /usr/local/redis/cluster/7001/data
# ========== 持久化配置 ==========
# RDB(必须开启,用于主从全量同步和故障恢复)
save 900 1
save 300 10
save 60 10000
# AOF(可选,集群模式建议开启)
appendonly yes
appendfilename "appendonly.aof"
# ========== 集群核心配置 ==========
cluster-enabled yes # 【关键】开启集群模式
cluster-config-file "nodes.conf" # 集群节点信息文件(自动生成,勿手动修改)
cluster-node-timeout 15000 # 节点超时时间(毫秒),超过此时间未响应判定为故障
# ========== 主从复制配置(仅在从节点配置) ==========
# 注意:集群模式下,从节点配置在创建集群时指定,或通过命令动态绑定
# 这里暂不配置 replicaof,后续通过 cluster replicate 命令绑定
核心参数说明:
cluster-enabled yes:开启集群模式,没有这一行 Redis 将以单机模式启动
cluster-node-timeout 15000:15 秒内无响应判定节点故障,集群内部自动处理
cluster-config-file:存储集群拓扑信息(节点 ID、角色、槽位分配),由 Redis 自动维护,禁止手动修改
5.3 批量生成配置文件
如果需要在一台机器上模拟多节点(如测试环境),可使用以下脚本快速生成
# 生成 7001 ~ 7006 的配置目录和文件
for port in 7001 7002 7003 7004 7005 7006; do
mkdir -p /usr/local/redis/cluster/${port}/{conf,logs,data}
cat > /usr/local/redis/cluster/${port}/conf/redis.conf << EOF
port ${port}
daemonize yes
bind 0.0.0.0
protected-mode no
logfile "/usr/local/redis/cluster/${port}/logs/redis.log"
dir /usr/local/redis/cluster/${port}/data"
save 900 1
save 300 10
save 60 10000
appendonly yes
appendfilename "appendonly.aof"
cluster-enabled yes
cluster-config-file "nodes.conf"
cluster-node-timeout 15000
EOF
done
5.4 启动所有节点
在 每台机器 上分别执行:
# Master1 机器
redis-server /usr/local/redis/cluster/7001/conf/redis.conf
# Master2 机器
redis-server /usr/local/redis/cluster/7002/conf/redis.conf
# ... 其他节点类似,各自启动自己的端口
验证所有节点启动成功:
ps -ef | grep redis
此时每个节点都只是一个独立的 Redis 实例,尚未形成集群。
六、创建集群(节点握手与槽位分配)
6.1 集群创建命令
使用 redis-cli --cluster create 命令将所有独立节点串联成集群:
redis-cli --cluster create \
192.168.10.11:7001 \
192.168.10.12:7002 \
192.168.10.13:7003 \
192.168.10.14:7004 \
192.168.10.15:7005 \
192.168.10.16:7006 \
--cluster-replicas 1
参数说明:
| 参数 | 含义 |
|---|---|
--cluster create |
创建集群 |
| 后面跟的 IP:Port 列表 | 集群所有节点地址 |
--cluster-replicas 1 |
每个主节点配 1 个从节点 |
执行后 Redis 会自动分配:
前三个节点(7001、7002、7003)被设为主节点
后三个节点(7004、7005、7006)被设为从节点
16384 个槽位平均分配给三个主节点
从节点随机绑定主节点(如需指定绑定关系,需后续手动调整)
执行过程中会提示确认:
>>> Performing hash slots allocation on 6 nodes...
Master[0] -> Slots 0 - 5460
Master[1] -> Slots 5461 - 10922
Master[2] -> Slots 10923 - 16383
Adding replica 192.168.10.14:7004 to 192.168.10.11:7001
Adding replica 192.168.10.15:7005 to 192.168.10.12:7002
Adding replica 192.168.10.16:7006 to 192.168.10.13:7003
>>> Trying to optimize slaves allocation for anti-affinity
[OK] All 16384 slots covered.
>>> Nodes configuration updated
>>> Assign a different config epoch to each node
>>> Sending CLUSTER MEET messages to join the cluster
输入 yes 确认创建。
6.2 为什么要指定 --cluster-replicas 1
-
Redis Cluster 需要用户明确告知主从关系
-
--cluster-replicas 1表示每个主节点需要 1 个副本(即 1 个从节点) -
集群总节点数 = 主节点数 × (1 + replicas)
-
示例中 6 个节点、replicas=1 → 6/(1+1) = 3 个主节点 + 3 个从节点
七、集群状态验证
7.1 查看集群信息
redis-cli -h 192.168.10.11 -p 7001 cluster info
关键输出字段解读:
cluster_state:ok # 集群状态:ok 表示正常
cluster_slots_assigned:16384 # 已分配的槽位总数
cluster_slots_ok:16384 # 状态正常的槽位数
cluster_slots_pfail:0 # 可能故障的槽位数
cluster_slots_fail:0 # 已故障的槽位数
cluster_known_nodes:6 # 集群已知节点数
cluster_size:3 # 主节点数量
cluster_current_epoch:6 # 当前配置纪元
cluster_my_epoch:1 # 本节点配置纪元
重点关注:
cluster_state:ok且cluster_slots_ok:16384,表示所有槽位正常覆盖。
7.2 查看节点列表
redis-cli -h 192.168.10.11 -p 7001 cluster nodes
输出示例与字段解读:
| 节点ID | IP:Port | 角色 | 主节点ID(仅从节点有) | 槽位范围 |
|---|---|---|---|---|
| 07c3dfb1... | 192.168.10.11:7001@17001 | myself,master | - | 0-5460 |
| a1b2c3d4... | 192.168.10.12:7002@17002 | master | - | 5461-10922 |
| e5f6g7h8... | 192.168.10.13:7003@17003 | master | - | 10923-16383 |
| i9j0k1l2... | 192.168.10.14:7004@17004 | slave | 07c3dfb1... | (复制 Master1) |
| m3n4o5p6... | 192.168.10.15:7005@17005 | slave | a1b2c3d4... | (复制 Master2) |
| q7r8s9t0... | 192.168.10.16:7006@17006 | slave | e5f6g7h8... | (复制 Master3) |
字段说明:
| 字段 | 含义 |
|---|---|
| 节点 ID | 集群内唯一标识,随机生成,重启不变 |
@17001 |
集群总线端口 = 普通端口 + 10000,节点间 Gossip 通信使用 |
myself |
表示当前连接的节点 |
master/slave |
节点角色 |
- |
从节点复制的主节点 ID,主节点显示 - |
0-5460 |
该主节点负责的哈希槽范围 |
7.3 测试数据分片
连接集群时需加 -c 参数开启集群模式(自动重定向):
redis-cli -h 192.168.10.11 -p 7001 -c
# 写入数据,观察重定向行为
> set name "zhangsan"
-> Redirected to slot [5798] located at 192.168.10.12:7002
OK
> set age 25
-> Redirected to slot [741] located at 192.168.10.11:7001
OK
> set city "beijing"
-> Redirected to slot [13308] located at 192.168.10.13:7003
OK
现象解读:
-
CRC16(name) % 16384 = 5798→ 属于 Master2(槽 5461-10922),自动重定向到 7002 -
CRC16(age) % 16384 = 741→ 属于 Master1(槽 0-5460),自动重定向到 7001 -
CRC16(city) % 16384 = 13308→ 属于 Master3(槽 10923-16383),自动重定向到 7003
核心理解:客户端连接任意节点写入数据,集群自动将请求路由到正确的节点,对应用透明。
7.4 验证从节点数据同步
# 连接 Slave1(7004)
redis-cli -h 192.168.10.14 -p 7004
# 直接读取会报错(数据不在这个节点)
> get name
(error) MOVED 5798 192.168.10.12:7002
# 使用 READONLY 命令允许从节点读
> READONLY
> get name
"zhangsan"
注意:集群模式下从节点默认不提供读服务,需执行
READONLY命令(或在配置中设置slave-read-only no)。
八、集群故障转移验证
8.1 模拟主节点宕机
# 关闭 Master2(192.168.10.12:7002)
redis-cli -h 192.168.10.12 -p 7002 shutdown
8.2 观察故障转移过程
在任意节点查看集群状态:
redis-cli -h 192.168.10.11 -p 7001 cluster nodes
变化观察:
# Master2 状态变为 fail
a1b2c3d4... 192.168.10.12:7002@17002 master,fail - 0 0 0 disconnected# Slave2 自动晋升为主节点
m3n4o5p6... 192.168.10.15:7005@17005 master - 5461-10922
整个过程全自动:从检测故障到从节点晋升,通常在
cluster-node-timeout的一到两倍时间内完成。
8.3 原主节点恢复后
# 重新启动 Master2
redis-server /usr/local/redis/cluster/7002/conf/redis.conf
# 再次查看集群状态
redis-cli -h 192.168.10.11 -p 7001 cluster nodes
恢复后的角色变化:
a1b2c3d4... 192.168.10.12:7002 slave m3n4o5p6... 5461-10922
原 Master2 自动变为 Slave2 的从节点,集群自动完成角色调整。
九、集群数据操作的重要限制
9.1 多 Key 操作限制
集群中不支持跨槽位的多 Key 操作,这是实际开发中最常见的坑。
# ❌ 错误示例:不同 Key 分布在不同槽位
> mset name "zhangsan" age 25
(error) CROSSSLOT Keys in request don't hash to the same slot
# ✅ 正确做法:使用 Hash Tag 强制 Key 落在同一槽位
> mset {user:1001}:name "zhangsan" {user:1001}:age 25
OK
9.2 Hash Tag 机制
规则:只对 Key 中 {} 内部的部分进行 CRC16 计算。
{user:1001}:name → CRC16("user:1001") % 16384 → 槽位固定
{user:1001}:age → CRC16("user:1001") % 16384 → 同一槽位
{user:1002}:name → CRC16("user:1002") % 16384 → 不同槽位
实际应用:将同一用户或同一业务实体的多个 Key 放在同一
{}组内,确保在同一个槽位,支持批量操作和事务。
9.3 事务限制
集群中的事务(MULTI/EXEC)也受槽位约束,事务中的所有 Key 必须在同一节点
# ✅ 正确:同一 Hash Tag,同一槽位
> MULTI
> set {user:1}:name "zhangsan"
> set {user:1}:age 25
> EXEC
# ❌ 错误:不同槽位
> MULTI
> set name "zhangsan"
> set age 25 # 两个 Key 不在同一槽位,事务失败
> EXEC
十、集群扩容与缩容简介
10.1 添加新主节点
# 1. 启动新节点(端口 7007)
redis-server /usr/local/redis/cluster/7007/conf/redis.conf
# 2. 将新节点加入集群
redis-cli --cluster add-node 192.168.10.17:7007 192.168.10.11:7001
# 3. 重新分片(迁移部分槽位到新节点)
redis-cli --cluster reshard 192.168.10.11:7001
# 按提示输入:要迁移的槽位数、目标节点ID、源节点ID
10.2 添加新从节点
redis-cli --cluster add-node 192.168.10.18:7008 192.168.10.11:7001 \
--cluster-slave \
--cluster-master-id <目标主节点ID>
10.3 删除节点
# 先迁移走该节点的槽位(如果是主节点),再删除
redis-cli --cluster del-node 192.168.10.11:7001 <节点ID>
十一、生产环境部署建议
11.1 节点数量与分布
| 建议 | 说明 |
|---|---|
| 至少 3 主 3 从 | 保证基础的高可用和数据分片 |
| 交叉部署 | 主从节点不能在同一台物理机上 |
| 多机房 | 异地多活场景,可将从节点部署在备用机房 |
11.2 防火墙端口
集群模式需要放行两个端口:
# Redis 服务端口
firewall-cmd --permanent --add-port=7001-7006/tcp
# 集群总线端口 = 服务端口 + 10000
firewall-cmd --permanent --add-port=17001-17006/tcp
firewall-cmd --reload
最容易遗漏:集群总线端口(服务端口+10000)用于节点间 Gossip 通信,忘记放行会导致节点互相不可见。
11.3 配置文件完整模板
port 7001
daemonize yes
bind 0.0.0.0
protected-mode no
logfile "/usr/local/redis/cluster/7001/logs/redis.log"
dir /usr/local/redis/cluster/7001/data
save 900 1
save 300 10
save 60 10000
appendonly yes
appendfilename "appendonly.aof"
cluster-enabled yes # 【核心】开启集群模式
cluster-config-file "nodes.conf" # 集群拓扑文件,自动维护
cluster-node-timeout 15000 # 节点超时时间(15秒)
cluster-require-full-coverage yes # 所有槽位必须被覆盖才接受写入
十二、Cluster vs Sentinel 对比总结
| 对比维度 | Sentinel 哨兵模式 | Cluster 集群模式 |
|---|---|---|
| 数据分片 | ❌ 不支持,全量数据每节点一份 | ✅ 支持,数据分散在多个主节点 |
| 内存上限 | 受单机限制 | 可水平扩展 |
| 写压力分担 | ❌ 只有主节点可写 | ✅ 多主节点同时写入 |
| 故障转移 | 依赖 Sentinel 集群 | 内置,无需额外组件 |
| 架构复杂度 | 较低 | 较高 |
| 客户端要求 | 支持普通 Redis 客户端 | 需支持 Cluster 协议的客户端 |
| 事务支持 | 完全支持 | 仅支持同槽位事务 |
| 适用场景 | 数据量可控、读多写少 | 海量数据、高并发写入 |
十三、总结
梳理了 Redis Cluster 集群模式 的原理、架构与搭建,核心要点回顾:
-
Cluster 解决的核心问题:数据水平分片 + 写压力分担,突破单机内存和 CPU 瓶颈
-
16384 个哈希槽 是分片基础,
CRC16(key) % 16384决定 Key 落在哪个主节点 -
去中心化 Gossip 协议 实现节点发现和故障检测,内置故障转移无需外部 Sentinel
-
跨槽位限制 是开发中最大坑点:用 Hash Tag
{}将关联 Key 约束到同一槽位 -
搭建关键命令:
redis-cli --cluster create ... --cluster-replicas 1 -
别忘放行总线端口:服务端口 + 10000,节点间通信依赖此端口
如有改进之处欢迎指正,觉得有帮助的话不妨点赞收藏支持一下,感谢!
更多推荐



所有评论(0)