Redis 集群如何实现数据分片与故障转移?

来源:网站建设经验作者:大象头衔:草根站长
导读:本期聚焦于大象创作的《Redis 集群如何实现数据分片与故障转移?》,敬请观看详情。为什么Redis集群在节点扩缩容时会出现部分key无法定位的情况?这要从它采用的哈希槽分片机制说起。Redis Cluster将16384个哈希槽均匀映射到多个主节点,每个key通过CRC16计算后对16384取模,再根据槽与节点的对应关系路由到目标节点。客户端执行命令时若访问了错误节点,会收到MOVED或ASK重定向响应,进而更新本地槽位缓存。故障转移方面,集群依靠Gossip协议进行节点间状态传播,当主节点被多数主节点标记为不可达时,其从节点会发起选举,获得超过半数主节点投票后晋升为新主节点。这一机制不依赖外部协调组件,但要求合理配置副本数和持久化策略,否则可能出现数据丢失或脑裂。理解分片路由和故障检测流程,是排查集群稳定性问题、设计高可用架构的基础。

Redis Cluster 是 Redis 官方提供的分布式解决方案,与主从复制加哨兵模式不同,它原生支持数据自动分片与节点故障转移。理解 Redis 集群的数据分布规则和故障恢复机制,有助于在生产环境中正确处理扩容、迁移、节点宕机等场景。本文将从哈希槽模型、客户端路由、故障检测与转移几个层面展开解析。

Redis 集群如何实现数据分片与故障转移?

哈希槽与数据分片模型

Redis Cluster 没有使用一致性哈希,而是将整个键空间划分为 16384 个哈希槽。每个主节点负责一部分槽位,节点启动后通过 cluster addslots 命令或配置文件声明自己管理的槽范围。客户端写入一个 key 时,会先根据 key 计算 CRC16 校验值,再对 16384 取模,得到 0 到 16383 之间的槽编号,最后将命令发送到负责该槽的节点。

这种固定槽位方案相比一致性哈希更加直观,节点扩容或缩容时只需要迁移部分槽位,而不是重新计算整个环上的虚拟节点。计算 slot 的典型代码如下:

import binascii

def crc16_slot(key):
    # Redis Cluster 使用 CRC16 后对 16384 取模
    return binascii.crc_hqx(key.encode(), 0) & 16383

print(crc16_slot("user:1001"))
print(crc16_slot("order:202401"))

如果 key 中包含花括号,Redis 只会对花括号内的部分进行哈希,这被称为 hash tag。例如 user:{1001}:name 和 user:{1001}:age 会落在同一个槽,适合需要事务或多键操作的业务。不过滥用 hash tag 会导致数据倾斜,需要根据实际 key 分布评估。

为什么是 16384 个槽?官方解释是 16384 在心跳包中可以用 2KB 的位图表示,既能保证节点间传播槽信息的开销较小,又足够细粒度地平衡数据。如果槽过少,迁移一个槽会一次性移动大量 key;如果过多,心跳消息中携带的槽位信息会膨胀。实际生产中使用 16384 已经能满足绝大多数集群规模。

客户端路由与 MOVED/ASK 重定向

当客户端向错误的节点发送命令时,Redis 会返回错误信息,而不是自动转发。普通客户端必须处理两种重定向:MOVED 表示槽已经永久迁移到其他节点,ASK 表示槽正在迁移过程中,仅对当前请求临时重定向。例如在迁移过程中访问一个 key,可能收到 ASK 错误,要求先执行 ASKING 命令再重新发送。

现代客户端大多内置了槽位缓存,被称为 Smart Client。它会在首次连接后执行 CLUSTER SLOTS 命令,将槽与节点的映射关系缓存到本地,之后直接计算 slot 并连接对应节点。MOVED 错误会触发缓存更新,而 ASK 错误不会改变缓存。以 redis-py 为例,集群模式通常在构造客户端时指定 RedisCluster,底层会自动完成路由和重定向。

以下命令可以观察手动访问错误节点时的重定向行为:

# 连接 7000 节点,设置一个实际属于 7001 节点的 key
redis-cli -p 7000 set username chen
(error) MOVED 14282 127.0.0.1:7001

# 使用 -c 参数让 redis-cli 自动跟随重定向
redis-cli -c -p 7000 set username chen
OK

MOVED 错误中包含了目标节点地址,客户端可以解析后重试。如果这个节点正在迁移槽,错误会变为 ASK,客户端需要先发送 ASKING 命令,再向目标节点发送原命令。这类机制保证了迁移期间请求不会丢失,但会增加一次额外往返。

故障检测与自动故障转移

Redis Cluster 使用 Gossip 协议在节点之间传播状态。每个节点默认每秒向随机几个节点发送 PING,收到 PONG 后更新最近通信时间。当某个主节点超过 cluster-node-timeout 仍无法响应时,其他节点会将其标记为 PFAIL,即可能失效。PFAIL 只是单节点主观判断,还需要多数主节点达成一致才会升级为 FAIL。

FAIL 状态一旦确定,该主节点的从节点会参与选举。选举条件包括从节点和主节点的复制偏移量不能差距过大,否则可能丢失已写入的数据。从节点会向其他主节点发送投票请求,获得超过半数主节点投票后,晋升为新主节点,并接管原主节点的所有槽位。原主节点恢复后会自动成为新主节点的从节点。

配置文件中与故障转移相关的参数如下:

# redis.conf 集群参数
cluster-enabled yes
cluster-config-file nodes.conf
cluster-node-timeout 5000
cluster-require-full-coverage yes
cluster-migration-barrier 1

cluster-require-full-coverage yes 表示任意槽位不可用时整个集群拒绝写请求,避免出现数据不一致但能保证完整性;如果改为 no,则部分槽不可用时集群仍可对外提供其他槽的读写,但可能产生部分数据丢失的风险。实际场景中需要根据业务可容忍性选择。

故障转移过程中的一个常见问题是脑裂。如果网络分区导致原主节点无法与其他节点通信,但客户端仍能访问它,而集群另一边已经选举出新主节点,就可能出现两个主节点同时写入同一批槽。Redis 通过多数派和配置纪元减少脑裂概率,但无法做到 100% 避免。通常建议每个主节点至少配置一个从节点,并让从节点分布在不同物理机或可用区。

集群扩缩容与运维注意点

集群运行过程中,增加节点或减少节点本质上是槽位迁移。使用 redis-cli --cluster add-node 添加新节点后,新节点默认不分片,需要通过 reshard 命令将部分槽从现有节点迁移过去。迁移过程中,Redis 会以槽为单位逐个移动 key,客户端可能遇到 ASK 错误,Smart Client 会处理这种临时重定向。

迁移时要特别注意大 key 的影响。如果某个 key 是数百 MB 的哈希或列表,迁移操作会阻塞对应节点的事件循环,导致该节点上的其他请求延迟升高。可以通过 redis-cli --bigkeys 扫描大 key,提前拆分或避免在业务高峰期迁移。另一个容易被忽略的问题是 cluster-config-file 路径权限,集群节点重启时会读取该文件恢复槽位信息,如果文件丢失或损坏,节点无法加入集群。

下面是一个检查集群槽位分布的示例:

redis-cli -p 7000 cluster slots
redis-cli -p 7000 cluster info
redis-cli -p 7000 cluster nodes

运维中还应该关注 cluster_state 是否为 ok,cluster_slots_assigned 是否等于 16384。如果某些槽未分配,集群会拒绝写入。通过这些命令可以快速定位分片异常和节点状态问题。

Redis集群数据分片故障转移修改时间:2026-09-22 00:28:09

免责声明:已尽一切努力确保本网站所含信息的准确性。网站作品多为原创整理与精心创作,观点力求客观中立。本站旨在免费分享,内容仅供个人学习、研究或参考使用。若引用了第三方作品,版权归原作者所有。如内容涉及您的权益,请联系我们进行处理Email:chomcom@qq.com。
引用或转载本作品时,请注明当前出处:https://www.ipipp.com/html/0922/60256.html,基于非商业用途的前提下,欢迎转载或二创本作品。
内容垂直聚焦
专注技术核心技术栏目,确保每篇文章深度聚焦于实用技能。从代码技巧到架构设计,为用户提供无干扰的纯技术知识沉淀,精准满足专业提升需求。
知识结构清晰
覆盖从开发到部署的全链路。AI、前端、编程、数据库、服务器、建站、系统层层递进,构建清晰学习路径,帮助用户系统化掌握开发与运维所需的核心技术。
深度技术解析
拒绝泛泛而谈,深入技术细节与实践难点。无论是数据库优化还是服务器配置,均结合真实场景与代码示例进行剖析,致力于提供可直接应用于工作的解决方案。
专业领域覆盖
精准对应开发生命周期。从前端界面到后端编程,从数据库操作到服务器运维,形成完整闭环,一站式满足全栈工程师和运维人员的技术需求。
即学即用高效
内容强调实操性,步骤清晰、代码完整。用户可根据教程直接复现和应用于自身项目,显著缩短从学习到实践的距离,快速解决开发中的具体问题。
持续更新保障
专注既定技术方向进行长期、稳定的内容输出。确保各栏目技术文章持续更新迭代,紧跟主流技术发展趋势,为用户提供经久不衰的学习价值。