Redis 高可用与集群方案
概述
Redis 单机无法满足生产环境的要求(单点故障、内存上限、写入瓶颈),本文覆盖持久化(RDB/AOF)、Sentinel 哨兵、Cluster 集群和常见运维命令。
持久化:RDB vs AOF
| 维度 | RDB(快照) | AOF(追加日志) |
|---|
| 原理 | fork 子进程,COW 内存快照 | 记录每条写命令到日志 |
| 文件大小 | 小(压缩二进制) | 大(文本命令) |
| 恢复速度 | 快 | 慢(需重放命令) |
| 数据安全 | 可能丢最近一次快照后的数据 | 最多丢 1 秒(everysec) / 不丢(always) |
| fork 风险 | 内存大时 fork 耗时、COW 引起内存翻倍 | 无 fork,但 IO 压力大 |
| 推荐频率 | save 900 1 + save 300 10 + save 60 10000 | appendfsync everysec |
生产推荐:RDB + AOF 混合持久化(Redis 4.0+)
# redis.conf
save 900 1
save 300 10
save 60 10000
appendonly yes
appendfsync everysec # 每秒刷盘
aof-use-rdb-preamble yes # 混合持久化:AOF 头部用 RDB 格式 + 尾部 AOF
auto-aof-rewrite-percentage 100 # AOF 增长 100% 时触发 rewrite
auto-aof-rewrite-min-size 64mb # AOF 至少 64MB 才考虑 rewrite
混合持久化:RDB 做全量快照、AOF 做增量,兼顾恢复速度和数据安全。
Sentinel 哨兵模式
架构
┌──────────┐
│ Sentinel │ (监控 + 通知 + 故障转移)
│ 集群 (≥3) │
└────┬─────┘
┌─────────┼─────────┐
↓ ↓ ↓
┌──────┐ ┌──────┐ ┌──────┐
│Master│←→│Slave │←→│Slave │
└──────┘ └──────┘ └──────┘
Sentinel 配置
# sentinel.conf
sentinel monitor mymaster 192.168.1.1 6379 2 # 2 个 Sentinel 认为 Master 挂了才启动故障转移
sentinel down-after-milliseconds mymaster 5000 # 5s 无响应判定主观下线
sentinel failover-timeout mymaster 30000 # 故障转移超时
sentinel parallel-syncs mymaster 1 # 新 Master 上线后同时同步的 Slave 数
故障转移流程
1. Sentinel 发现 Master 主观下线(SDOWN)
2. 达到 quorum 数后判定客观下线(ODOWN)
3. 选举 Leader Sentinel 执行故障转移
4. 从 Slave 中选择最优(复制偏移量最大、优先级高)
5. 选举出的 Slave 执行 SLAVEOF NO ONE → 成为新 Master
6. 其他 Slave 切换到新 Master
7. 旧 Master 恢复后自动变为 Slave
Sentinel 限制
| 限制 | 说明 |
|---|
| 本质是主从 | 只有一个 Master,写入能力不扩展 |
| 客户端需感知 | 客户端需支持 Sentinel 协议获取 Master 地址 |
| 切换期间不可写 | 故障转移期间短暂不可用 |
| 数据丢失窗口 | 异步复制 + 切换期间可能丢少量数据 |
Cluster 集群模式
核心概念
Redis Cluster = 分片(Sharding)+ 主从(Replication)
16384 个 Hash Slot:
Master 0: 0-5460
Master 1: 5461-10922
Master 2: 10923-16383
每个 Master 有 N 个 Slave 副本
Cluster 配置
# redis.conf
cluster-enabled yes
cluster-config-file nodes.conf
cluster-node-timeout 5000 # 节点不可达超时(ms)
cluster-require-full-coverage yes # 有 Slot 不可用则拒绝请求
cluster-migration-barrier 1 # Slave 迁移门槛
Cluster 创建与扩容
# 创建集群(6 个节点:3 主 + 3 从)
redis-cli --cluster create \
192.168.1.1:6379 192.168.1.2:6379 192.168.1.3:6379 \
192.168.1.4:6379 192.168.1.5:6379 192.168.1.6:6379 \
--cluster-replicas 1
# 添加新 Master(扩容)
redis-cli --cluster add-node 192.168.1.7:6379 192.168.1.1:6379
redis-cli --cluster reshard 192.168.1.7:6379 # 重新分配 Slot
# 添加 Slave
redis-cli --cluster add-node 192.168.1.8:6379 192.168.1.1:6379 \
--cluster-slave --cluster-master-id <master-id>
# 查看集群状态
redis-cli --cluster info 192.168.1.1:6379
redis-cli --cluster check 192.168.1.1:6379
Cluster 使用限制
| 限制 | 说明 | 应对 |
|---|
| 批量操作需 key 在同一 Slot | mget 跨 Slot 报错 | 用 Hash Tag {user}:1001:info {user}:1001:ext |
| 事务仅单个 Slot | MULTI/EXEC 不能跨节点 | 设计保证相关 key 同一 Slot |
| Pipeline 按节点分组 | 客户端需自行路由 | JedisCluster/lettuce 自动处理 |
| Pub/Sub 影响所有节点 | 发布消息广播到全集群 | 大规模 Pub/Sub 建议用 Kafka |
# Hash Tag 示例:确保同一 Slot
SET {user:1001}:name "Alice"
SET {user:1001}:email "alice@example.com"
# 两个 key 在同一个 Slot(只算 {} 内的部分做 hash)
Sentinel vs Cluster 选型
| 维度 | Sentinel | Cluster |
|---|
| 数据量 | < 内存单机上限 | 可扩展到 TB 级 |
| 写入 QPS | 单机 | 线性扩展 |
| 架构复杂度 | 简单 | 中等 |
| 运维成本 | 低 | 中 |
| 客户端兼容性 | 需 Sentinel 感知 | 需 Cluster 感知 |
| 多 key 操作 | 原生支持 | 需 Hash Tag |
| 适用规模 | 中小规模 | 大规模/高写入 |
选型建议: 10 亿以下 key、写入 < 10 万 QPS → Sentinel;超大规模或快速增长 → Cluster。K8s 环境首选 Redis Operator。
运维命令速查
# === 信息查看 ===
redis-cli INFO # 完整信息
redis-cli INFO replication # 复制状态
redis-cli INFO stats # 统计信息
redis-cli INFO memory # 内存使用
redis-cli INFO persistence # 持久化状态
# === 延迟诊断 ===
redis-cli --latency # 实时延迟
redis-cli --latency-history # 延迟历史
redis-cli --latency-dist # 延迟分布
redis-cli --intrinsic-latency 60 # 本机固有延迟(排除网络)
# === 内存诊断 ===
redis-cli --bigkeys # BigKey 扫描
redis-cli MEMORY DOCTOR # 内存分析建议
redis-cli MEMORY STATS # 内存统计
# === 主从管理 ===
redis-cli SLAVEOF host port # 将当前节点变为 Slave
redis-cli SLAVEOF NO ONE # 将当前节点变为 Master
redis-cli ROLE # 查看当前角色
# === 慢查询日志 ===
redis-cli SLOWLOG GET 10 # 最近 10 条慢查询
redis-cli SLOWLOG LEN # 慢查询条数
redis-cli SLOWLOG RESET # 清空慢查询日志
# === 连接数 ===
redis-cli CLIENT LIST # 所有连接
redis-cli CLIENT KILL addr:port # KILL 连接
redis-cli CLIENT PAUSE 5000 # 暂停处理命令 5 秒(用于主从切换)
关键参数调优
# redis.conf 生产建议
# 内存
maxmemory 4gb # 最大内存(避免 OOM)
maxmemory-policy allkeys-lru # 淘汰策略:LRU
# 持久化
save 900 1
save 300 10
save 60 10000
appendonly yes
appendfsync everysec
aof-use-rdb-preamble yes
# 超时与连接
timeout 300 # 空闲连接超时(秒)
tcp-keepalive 300 # TCP keepalive
maxclients 10000
# 慢查询日志
slowlog-log-slower-than 10000 # 超过 10ms 记录(微秒)
slowlog-max-len 128
# 禁用危险命令
rename-command FLUSHDB ""
rename-command FLUSHALL ""
rename-command KEYS ""
常见问题 / 坑点
| 问题 | 原因 | 解决方案 |
|---|
| RDB fork 导致延迟飙升 | 大内存 fork 阻塞 | 降低 save 频率 + 使用混合持久化 + 关闭 THP |
| AOF rewrite 时 IO 打满 | rewrite 大量写盘 | 增大 auto-aof-rewrite-min-size + SSD |
| Sentinel 脑裂 | 网络分区 | 确保 quorum > N/2 节点 + min-slaves-to-write=1 |
| Cluster 数据迁移时客户端重定向慢 | MOVED/ASK 重定向 | 客户端保持连接池、支持 pipelining |
| OOM 被 OS kill | maxmemory 未设或太小 | 设置合理 maxmemory + maxmemory-policy |
KEYS * 阻塞 | 遍历全部 key(O(N)) | 禁用 KEYS,用 SCAN 替代 |
关联知识
参考资源
学习时间
| 阶段 | 时间 | 备注 |
|---|
| 初次学习 | 2026-07-14 | 持久化 + Sentinel + Cluster + 运维 |
状态: 📖 已掌握
下次复习日期: 2026-08-14