Redis集群如何安全地进行节点扩容和缩容?

来源:PHP编程网作者:重启一下头衔:草根站长
导读:本期聚焦于重启一下创作的《Redis集群如何安全地进行节点扩容和缩容?》,敬请观看详情。直接在生产环境执行redis-cli --cluster reshard命令而不预先规划槽位迁移,很容易导致集群阻塞甚至数据不一致。Redis集群的扩容和缩容并非简单地把新节点加入或摘除,它涉及槽位重新分配、数据迁移、客户端路由感知等多个环节。本文从操作前检查、节点添加、槽位迁移、节点摘除到验证回滚,完整梳理一套可落地的步骤。特别提醒目标节点必须提前清空数据、迁移过程中要控制并发与超时、缩容前务必先迁移所有槽位再删除节点,否则会触发主从切换或数据丢失。文中命令基于redis-cli集群模式,并给出每一步的确认与回退方案,帮助运维人员把变更风险降到最低。

Redis集群采用虚拟槽分区机制,将16384个哈希槽均匀分配到多个主节点上。每个节点负责一部分槽位,客户端通过CRC16(key)%16384计算槽号并路由到对应节点。当业务数据量增长超过单节点承载能力,或者需要下线部分机器时,必须在保证数据一致性和可用性的前提下调整集群拓扑。扩容就是增加新节点并迁移部分槽位,缩容则是先迁走槽位再移除节点。整个过程涉及槽位规划、数据迁移和客户端感知,操作不当可能造成数据丢失或服务中断。

Redis集群如何安全地进行节点扩容和缩容?

一、扩容缩容前的关键概念与检查项

执行任何集群变更之前,必须先确认集群当前状态是健康的。使用redis-cli -p 7000 cluster info查看集群状态,重点看cluster_state是否为ok,以及cluster_slots_assigned是否等于16384。如果槽位没有全部分配,或者存在fail状态的节点,需要先修复再操作。同时要确认所有节点使用的Redis版本一致,尤其是集群模式下的协议兼容性,版本差异过大会导致节点无法正常通信。

另一个关键点是理解节点ID和集群总线端口。每个Redis集群节点除了对外服务端口外,还会使用服务端口加10000的集群总线端口进行节点间通信,例如服务端口7000对应的总线端口是17000。防火墙或安全组必须同时放行这两个端口,否则新节点加入后会出现握手失败。此外,目标新节点必须是干净的、没有数据且没有配置cluster-enabled yes之外的旧集群信息。如果之前加入过其他集群,需要清空数据目录和配置中的cluster-config-file,避免残留的节点ID冲突。

在扩容前还要规划槽位迁移比例。假设原集群有3个主节点,每个节点大约承载5461个槽位,新增一个主节点后理想情况是每个节点约4096个槽位。这个比例决定迁移的数据量和耗时,也影响迁移过程中的网络带宽和内存压力。建议在业务低峰期操作,并为每次迁移设置合理的超时时间。

二、节点扩容操作:添加主节点与从节点

Redis官方提供了redis-cli --cluster命令来简化集群管理。添加主节点的命令格式如下:

# 将新节点 127.0.0.1:7006 加入已有集群
redis-cli --cluster add-node 127.0.0.1:7006 127.0.0.1:7000

这条命令中,127.0.0.1:7006是待加入的新节点地址,127.0.0.1:7000是集群中任意一个现有节点地址。执行后,新节点会被分配一个随机节点ID,并以空槽位的主节点身份加入集群。此时使用redis-cli -p 7000 cluster nodes可以看到新节点已经出现在节点列表中,但它的connected状态可能带有no slots标记,表示还没有负责任何槽位。

如果希望新节点作为从节点加入,需要指定--cluster-slave参数,并可选通过--cluster-master-id指定要跟随的主节点ID。例如:

# 将 127.0.0.1:7007 作为从节点加入,并跟随节点ID为 abc123 的主节点
redis-cli --cluster add-node 127.0.0.1:7007 127.0.0.1:7000 --cluster-slave --cluster-master-id abc123

从节点加入后会自动同步主节点的数据,不需要手动迁移槽位。如果省略--cluster-master-id,系统会随机选择一个主节点作为复制目标。对于需要提高读性能或增加容灾能力的场景,建议为每个主节点配置至少一个从节点。

主节点加入后,需要为其分配槽位并迁移数据。使用redis-cli --cluster reshard命令,交互式输入迁移槽位数、目标节点ID和源节点ID。也可以使用非交互模式批量执行:

# 从所有现有主节点迁移共4096个槽位到新节点
redis-cli --cluster reshard 127.0.0.1:7000 --cluster-from all --cluster-to <target-node-id> --cluster-slots 4096 --cluster-yes

其中<target-node-id>要替换为新节点的真实节点ID。迁移过程会逐个槽位进行,每个槽位的所有键会通过MIGRATE命令原子地转移到目标节点。为了保证集群可用性,Redis采用在线迁移方式,源节点在迁移期间仍然对外提供服务,只有在单个槽位完成迁移的短暂瞬间会阻塞该槽位的请求。因此迁移过程对业务的影响是局部且可控的。

迁移完成后,建议执行redis-cli --cluster check 127.0.0.1:7000检查集群健康状态,确认所有槽位都已分配到节点且每个节点负责的槽位范围符合预期。同时可以查看cluster nodes的输出,确认新节点已经拥有对应数量的槽位。

三、节点缩容操作:槽位迁出与节点移除

缩容节点比扩容更危险,因为如果直接删除一个仍持有槽位的主节点,会导致这些槽位的数据不可用,甚至触发集群进入fail状态。正确的顺序是先将待下线节点的所有槽位迁移到其他节点,确认槽位全部迁出后,再使用del-node命令移除节点。

假设要下线的节点ID为old-node-id,可以先使用redis-cli --cluster reshard把它的槽位迁移到另一个主节点。交互模式中指定源节点为待下线节点,目标节点为剩余的主节点,迁移槽位数量等于该节点当前持有的槽位数。也可以使用非交互模式:

# 将 old-node-id 的所有槽位迁移到 new-node-id
redis-cli --cluster reshard 127.0.0.1:7000 --cluster-from <old-node-id> --cluster-to <new-node-id> --cluster-slots 5461 --cluster-yes

迁移完成后,通过cluster nodes确认待下线节点已经没有槽位,其标识中不再包含槽位范围信息。此时执行del-node命令移除节点:

# 从集群中删除节点
redis-cli --cluster del-node 127.0.0.1:7000 <old-node-id>

如果待下线节点有从节点,需要先删除从节点,再删除主节点。从节点没有槽位,可以直接使用del-node删除。删除后集群会自动更新配置,其他节点会感知到拓扑变化。

缩容过程中一个常见误区是忽略客户端连接会缓存槽位映射。即使槽位已经迁走,部分客户端仍然会尝试向旧节点发送请求。虽然Redis集群会返回MOVED重定向响应,但旧节点被删除后,客户端会收到连接错误。因此建议在缩容前提前通知业务方,或者在客户端层面主动刷新集群拓扑。对于使用Proxy架构的客户端,如Codis或Twemproxy,需要确保代理层支持动态更新节点列表。

四、常见错误与线上操作最佳实践

一个非常典型的错误是直接使用普通Redis实例的方式启动新节点并执行cluster meet,然后手动分配槽位。虽然cluster meet也能让节点加入集群,但后续的槽位迁移和节点管理容易遗漏配置持久化,导致重启后集群失联。官方推荐的redis-cli --cluster命令会自动处理配置同步和节点握手,是最稳妥的方式。

另一个常见问题是迁移过程中没有设置--cluster-timeout,遇到大量数据或慢网络时迁移失败。可以在命令中添加--cluster-timeout 5000来指定每次槽位迁移的超时时间,单位是毫秒。迁移大量数据时,建议分批进行,例如每次迁移500个槽位,观察集群延迟和内存使用后再继续。这样即使出现问题,影响范围也有限,回退起来更容易。

线上操作的最佳实践可以总结为:第一,变更前完整备份RDB文件和集群配置;第二,始终在集群健康状态下操作,避免在已有节点故障时进行扩容缩容;第三,使用--cluster-yes前先在测试环境演练一遍;第四,迁移过程中持续监控cluster info中的cluster_known_nodescluster_slots_ok等指标;第五,缩容完成后保留一段时间空节点不要立即下线,观察客户端是否还有陈旧路由请求。这样做可以把Redis集群拓扑调整的风险降到最低。

Redis集群节点扩容节点缩容修改时间:2026-08-21 01:35:29

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