Redis 系列(十一):高可用(二)——Redis Cluster 集群

核心目标:理解 16384 个哈希槽的分片原理、gossip 通信与 MOVED/ASK 重定向;能搭建三主三从集群;理解集群模式的功能限制(CROSSSLOT、db0 only、多 key 命令);能评估"哨兵 + 主从"与"集群"的选型。

前置知识 :完成 Part 10(复制与故障转移------集群分片内仍依赖这些机制)。

验证环境 :Redis 8.10.0(cygwin 移植版);三主三从共 6 个隔离实例(6380-6385),redis-cli --cluster 创建。最后复核日期:2026-08-07。


0. 本篇问题场景:单主库的天花板

哨兵解决了"主库挂了自动切换",但仍有三个上限:

  1. 写容量:所有写都打在一个主库,单线程 CPU 饱和后加机器没用;
  2. 内存容量:数据总量受单机内存限制,换大内存机器有成本上限;
  3. 故障半径:一次主库宕机,整个数据集不可写。

Redis Cluster 的答案:分片------把 16384 个哈希槽摊到多个主节点,每个主节点只服务自己那部分槽。写能力、内存容量、故障半径随之分摊。


1. 分片模型:16384 个哈希槽

1.1 槽的分配

text 复制代码
CLUSTER KEYSLOT order:1001     → slot 241      (节点 A)
CLUSTER KEYSLOT user:42        → slot 15880    (节点 C)
CLUSTER KEYSLOT product:9      → slot 264      (节点 A)

本实验三主节点分片(redis-cli --cluster create 自动分配):

text 复制代码
127.0.0.1:6380  master  slots:[0-5460]
127.0.0.1:6381  master  slots:[5461-10922]
127.0.0.1:6382  master  slots:[10923-16383]
+ 6383/6384/6385 分别为三个主的从库

cluster info 的健康指标:

text 复制代码
cluster_state:ok
cluster_slots_assigned:16384    ← 槽全部有归属
cluster_known_nodes:6           ← 主从共 6 个节点

1.2 槽的计算:CRC16

text 复制代码
slot = CRC16(key) % 16384

16384 是固定值(不是节点数!)------槽是"逻辑位置",节点是"物理位置",两者解耦后,扩容/缩容只需要迁移槽,不需要重新哈希全部数据。


2. 请求路由:MOVED 与 ASK

2.1 MOVED:槽在别人那

客户端直连节点 A 请求一个属于节点 C 的 key,节点 A 返回 MOVED:

text 复制代码
$ redis-cli -p 6380 GET user:42
MOVED 15880 127.0.0.1:6382

MOVED 15880 127.0.0.1:6382 = "slot 15880 在 6382,去那里"。智能客户端(redis-py 的 RedisCluster、redis-cli -c)会缓存槽-节点映射并自动重定向:

text 复制代码
$ redis-cli -c -p 6380 SET user:42 "alice"
OK
$ redis-cli -c -p 6380 GET user:42
alice

2.2 ASK:槽正在迁移

槽迁移(扩容/缩容)期间,部分 key 已搬到目标节点。源节点对已搬走的 key 返回 ASK------与 MOVED 的区别:

MOVED ASK
含义 槽已永久属于对方 槽正在迁移,这个 key 暂时在对方
客户端处理 更新槽映射缓存 只重定向这一次,不更新缓存
text 复制代码
ASK 15880 127.0.0.1:6382

2.3 集群模式的功能限制

单节点可以跨 key 操作(MGET、事务、Lua),但槽不同就报 CROSSSLOT:

text 复制代码
$ redis-cli -p 6380 MGET order:1001 user:42
(error) CROSSSLOT Keys in request don't hash to the same slot

集群模式下的限制汇总:

能力 限制
多 key 命令(MGET/MSET/SUNION...) 所有 key 必须同槽
MULTI 事务 / Lua 脚本 涉及的 key 必须同槽
SELECT 只有 db 0
管道/发布订阅 部分支持,跨槽受限
单 key 大对象 不受限,但会倾斜(Part 4 大 key 危害放大)

2.4 hash tag:把相关 key 钉进同一槽

官方 7.4 支持 hash tag :key 中 {...} 部分参与哈希,其余忽略。user:{42}:name 与 user:{42}:cart 同槽,从而支持同槽 MGET/事务/Lua。

⚠️ 本机 8.10.0(cygwin 移植版)实测 hash tag 未生效 :CLUSTER KEYSLOT "user:{42}:name" = 6755、"user:{42}:cart" = 12984,不同槽!官方实现(cluster.c 的 keyHashSlot)应取 {} 内子串做 CRC16,本机移植版行为不符。该结论仅基于本机 8.10.0 移植版实测,标准发行版请在目标环境用 CLUSTER KEYSLOT 复核。

工程教训 :hash tag 是"跨 key 操作"的前提,上线前必须用 CLUSTER KEYSLOT 实测确认 tag 生效,不能默认所有发行版行为一致。若 tag 不可用,跨 key 业务要么改单实例,要么应用层聚合。


3. 主从与故障转移

集群的每个分片仍是一主一从(复制机制同 Part 10)。从库不参与分片,只做副本:

  • 主节点宕机 → 从库通过 gossip 检测(cluster-node-timeout,默认 15 秒)→ 从库自动提升为新主(无需哨兵!哨兵是集群外的独立组件,集群自带选举);
  • 数据与角色转移演示(本实验手动触发 CLUSTER FAILOVER):
text 复制代码
$ redis-cli -p 6383 CLUSTER FAILOVER     # 6383 是 6380 的从
OK
$ redis-cli -p 6383 cluster nodes
127.0.0.1:6383@16383 myself,master       ← 从库接管成为主
$ redis-cli -p 6383 cluster info
cluster_state:ok                          ← 集群仍健康
$ redis-cli -c -p 6383 GET order:1001
paid                                      ← 数据可继续访问

自动故障转移同样有"检测时间 + 选举"的不可用窗口(默认 15 秒级),且部分分片宕机时,只有该分片的槽不可用------这是集群相对哨兵(整个数据集)的故障半径优势。


4. 扩容缩容:槽迁移

扩容 = 加节点 → 从现有主节点迁出部分槽 (reshard):

text 复制代码
# 交互式迁移(或 --cluster-from/--cluster-to 指定源与目标)
redis-cli --cluster reshard 127.0.0.1:6380 \
  --cluster-from <源节点id> --cluster-to <新节点id> \
  --cluster-slots 1000 --cluster-yes

迁移期间访问中的 key 返回 ASK (§2.2),客户端需要处理。缩容同理反向迁移。槽迁移是数据拷贝,期间有内存/带宽开销------扩容要在低峰期做,且新节点先以"空槽主节点"加入。


5. 选型:哨兵 + 主从 vs 集群

维度 哨兵 + 主从 Redis Cluster
数据容量 单主上限 横向扩展(多分片)
写能力 单主上限 随分片增长
故障半径 整个数据集切换 仅宕机分片
复杂度 低(哨兵配置 + 客户端) 高(槽、重定向、跨槽限制)
跨 key 操作 无限制 受 CROSSSLOT 限制
适用 数据量 < 单机、写 QPS 可控 数据量/写 QPS 超单机

结论 :能单机就单机,需要高可用加哨兵;只有当单机内存或写吞吐成为瓶颈时再上集群------集群的跨槽限制会反过来约束业务(多 key 操作、事务、Lua)。


6. 版本与环境差异

差异点 官方 7.4 本机 8.10.0(cygwin 移植版)
槽分配/重定向 一致 一致(MOVED/ASK 实测正常)
hash tag keyHashSlot 支持 {} 实测未生效(§2.4)------上线前必须实测
故障转移 gossip + 从库提升 一致
集群命令 redis-cli --cluster 可用

7. 测试与验收

  • 集群测试(隔离环境):槽全覆盖(16384)、MOVED/ASK 重定向、CROSSSLOT 拒绝、CLUSTER FAILOVER 后数据可访问;
  • hash tag 验收:CLUSTER KEYSLOT 实测 {tag}:a 与 {tag}:b 同槽(本机环境不满足!)。

本篇验收清单:

  • 能解释"16384 槽 vs 节点数"的解耦设计(扩容只需迁槽);
  • 能区分 MOVED(永久归属)与 ASK(迁移中临时指向);
  • 能说出集群模式下跨 key 操作的限制(CROSSSLOT)与 hash tag 的作用;
  • 知道集群自带的从库提升机制与哨兵的差异;
  • 能在"哨兵 + 主从"与"集群"之间给出选型依据;
  • 搭建过三主三从集群并完成一次接管演练。

8. 常见误区

  1. "集群 = 多台机器各存各的" ------是槽分片不是节点分片,节点只是槽的宿主;扩容迁移的是槽。
  2. "集群可以替代哨兵"------集群自带故障转移,但跨 key 限制让很多业务无法直接迁移;小数据量上集群得不偿失(§5)。
  3. "hash tag 所有版本都支持" ------本机 8.10 移植版实测不生效;必须 CLUSTER KEYSLOT 验证(§2.4)。
  4. "MOVED 和 ASK 一样"------MOVED 永久更新路由缓存,ASK 只重定向单次(§2.2)。
  5. "集群里随便 MGET"------跨槽报 CROSSSLOT;需要同槽(hash tag)或应用层聚合。

9. 本篇小结

  • 分片:16384 槽解耦"逻辑位置"与"物理节点",扩容=迁槽;
  • 路由:MOVED(槽迁移后)/ ASK(槽迁移中)两种重定向;
  • 限制 :跨槽多 key 操作被 CROSSSLOT 拒绝,hash tag 是解药但必须实测;
  • 选型:单机 → 哨兵 → 集群,逐级升级,集群的复杂度要用"确实超单机"来换取。

至此高可用三件套(复制、哨兵、集群)讲完。最后一篇 Part 12:性能、观测与生产排障 把整条知识链收拢到"问题怎么查":慢查询、延迟、大 key、热 key、连接治理与排障决策树。


10. 官方资料

相关推荐
IvorySQL6 分钟前
从轮询到等待——PostgreSQL WAIT FOR LSN 特性深度解析
数据库·postgresql
OceanBase数据库官方博客44 分钟前
被 VLDB 2027接收OceanBase 最新论文让数据库基(技术解析与实践)
数据库·人工智能·oceanbase
创邻科技1 小时前
国产图数据库刷新 LDBC 世界纪录:创邻科技 Galaxybase 在 SF100、SF300、SF1000 测试中全面领先”
数据库·科技
GreatSQL社区2 小时前
主从复制SQL线程中断——字符集砸出的坑
java·数据库·算法
XLYcmy2 小时前
AI 赋能后中文与英文数据库对比分析报告 上
数据库·ai·llm·prompt·检索·wos·cnki
这个DBA有点耶2 小时前
ELT 工具选型完整指南:从 ETL 差异分析到工程落地
数据库·架构·代码规范
IvorySQL3 小时前
PostgreSQL 日报|堆表选择性索引更新(10 月 13 日)
数据库·人工智能·postgresql·开源·区块链
张洛闻Eren3 小时前
Ansible【第一课】:Ansible介绍
运维·数据库·云原生·kubernetes·github·ansible
深圳市益普科技有限公司3 小时前
中小封装厂上 MES,为什么十个项目九个坑?
大数据·数据库·人工智能
云边云科技_云网融合3 小时前
从 POS 机到访客 Wi-Fi:零售门店安全建设的完整解法
服务器·网络·数据库