目录

哨兵(Sentinel)模式

一、哨兵模式概述

1.1 主从架构的痛点回顾

1.2 哨兵是什么

1.3 哨兵的核心能力

二、哨兵架构与工作原理

2.1 为什么需要多个哨兵

2.2 哨兵集群架构图

2.3 主观下线(SDOWN)与客观下线(ODOWN)

2.4 故障转移完整流程

2.5 从节点选举优先级规则

三、实验环境规划

四、哨兵模式搭建步骤

4.1 前提:已完成主从架构

4.2 哨兵配置文件

4.3 核心参数详解

4.4 启动哨兵

五、哨兵状态验证

5.1 连接哨兵查看信息

查看主节点信息

查看从节点列表

查看哨兵集群成员

5.2 观察哨兵日志

六、故障转移实战验证

6.1 模拟主节点宕机

6.2 观察哨兵日志

6.3 验证新主节点

6.4 原主节点恢复后

七、Java 客户端连接哨兵

7.1 Jedis 连接示例

7.2 Spring Boot 连接配置(Lettuce / Jedis)

八、哨兵模式的局限性

min-slaves-to-write 配置详解

一、配置定义

二、配置语法

三、工作原理

四、这个配置解决什么问题

五、生产环境配置建议

六、与哨兵的配合

七、注意事项

九、生产环境部署建议

9.1 哨兵节点数量

9.2 哨兵部署位置

9.3 防火墙端口

9.4 推荐配置汇总

十、总结

集群模式

一、Cluster 集群概述

1.1 前三大架构的演进回顾

1.2 什么是 Redis Cluster

1.3 Cluster 核心能力

二、数据分片原理(核心机制)

2.1 虚拟哈希槽(Hash Slot)

2.2 为什么是 16384 个槽

2.3 为什么不用一致性哈希

三、Cluster 架构设计

3.1 典型架构:三主三从

3.2 Gossip 协议

四、实验环境规划

五、Cluster 集群搭建步骤

5.1 前提准备

5.2 单节点配置文件

5.3 批量生成配置文件

5.4 启动所有节点

六、创建集群(节点握手与槽位分配)

6.1 集群创建命令

6.2 为什么要指定 --cluster-replicas 1

七、集群状态验证

7.1 查看集群信息

7.2 查看节点列表

7.3 测试数据分片

7.4 验证从节点数据同步

八、集群故障转移验证

8.1 模拟主节点宕机

8.2 观察故障转移过程

8.3 原主节点恢复后

九、集群数据操作的重要限制

9.1 多 Key 操作限制

9.2 Hash Tag 机制

9.3 事务限制

十、集群扩容与缩容简介

10.1 添加新主节点

10.2 添加新从节点

10.3 删除节点

十一、生产环境部署建议

11.1 节点数量与分布

11.2 防火墙端口

11.3 配置文件完整模板

十二、Cluster vs Sentinel 对比总结

十三、总结


哨兵(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 故障转移完整流程

  1. 多个哨兵发现主节点不可达,标记为 SDOWN

  2. SDOWN 数量达到 quorum确认 ODOWN

  3. 哨兵集群进行 领导者选举(Raft 算法变体),选出执行故障转移的哨兵

  4. 领导者哨兵在存活的从节点中 选举最优从节点 作为新主节点

  5. 将选中的从节点 执行 slaveof no one,升级为主节点

  6. 通知其余从节点 重新 slaveof 到新主节点

  7. 将故障的原主节点降为从节点(待其恢复后自动加入)

  8. 通知客户端 主节点地址已变更

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 秒,触发故障转移(保服务可用)

  • 两者配合,数据安全 + 服务可用 兼顾

七、注意事项
  1. 不适合所有业务:对写入可用性要求极高的场景(如实时性日志、临时缓存),这个配置可能导致写入失败,需谨慎评估

  2. 必须两个参数同时设置:只设 min-replicas-to-write 不设 min-replicas-max-lag 无效

  3. 动态调整:可通过 CONFIG SET 在线修改,无需重启

  4. 建议写入配置文件:重启后生效,避免动态修改后忘记持久化

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 哨兵模式 的原理与部署:

    1. 哨兵不是存储层,而是独立的监控与控制进程

    2. SDOWN → ODOWN → 领导者选举 → 从节点选举 → 自动切换 是完整故障转移链路

    3. quorum 确认 ODOWNmajority 选领导者,两者含义不同

    4. 客户端通过 哨兵发现主节点,切换后自动感知,无需人工改配置

    5. 哨兵模式解决了 高可用,但写压力和内存容量问题留给 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 集群模式 的原理、架构与搭建,核心要点回顾:

    1. Cluster 解决的核心问题:数据水平分片 + 写压力分担,突破单机内存和 CPU 瓶颈

    2. 16384 个哈希槽 是分片基础,CRC16(key) % 16384 决定 Key 落在哪个主节点

    3. 去中心化 Gossip 协议 实现节点发现和故障检测,内置故障转移无需外部 Sentinel

    4. 跨槽位限制 是开发中最大坑点:用 Hash Tag {} 将关联 Key 约束到同一槽位

    5. 搭建关键命令redis-cli --cluster create ... --cluster-replicas 1

    6. 别忘放行总线端口:服务端口 + 10000,节点间通信依赖此端口

    如有改进之处欢迎指正,觉得有帮助的话不妨点赞收藏支持一下,感谢!

    Logo

    汇聚全球AI编程工具,助力开发者即刻编程。

    更多推荐