Redis集群模式是官方提供的分布式运行方案,核心目标是把数据自动切分到多个节点,同时保留一定的可用性。它不像哨兵模式那样只做高可用,而是同时解决单机内存上限和写入吞吐问题。部署最小化集群需要至少六个实例,三主三从,本文会把这六个节点从配置到测试完整走一遍。

一、Redis集群模式的核心机制
Redis集群并没有采用一致性哈希,而是引入了固定数量的哈希槽。整个集群把数据空间划分为16384个槽,每个key通过CRC16算法计算出一个值,再对16384取模,最终落到某个槽上。主节点之间会协商各自负责的槽区间,例如第一个主节点负责0到5460,第二个负责5461到10922,第三个负责10923到16383。这种设计让槽迁移变得非常清晰,当需要扩容时,只需把部分槽从旧节点迁移到新节点,不会影响其他槽的数据访问。
节点之间通过Gossip协议持续交换集群状态,包括哪些节点在线、哪些槽由谁负责、主从关系如何。每个Redis节点都保存了一份完整的集群元数据,因此客户端连接任意一个节点都能获取槽映射。如果请求的key不属于当前节点,服务端会返回MOVED错误,并在错误信息中附带目标节点的地址。支持集群协议的客户端会自动更新本地映射并重新发送请求,这个过程对应用层基本透明。
高可用依赖主从复制和自动故障转移。每个主节点建议至少挂一个从节点,从节点与主节点保持异步复制。当主节点超过cluster-node-timeout时间无法联系时,集群中的其他主节点会发起投票,从节点被选举为新的主节点,并接管原主节点的槽。为了保证投票有效,集群至少需要三个主节点,否则无法形成多数派。这也是为什么官方推荐三主三从而不是两主两从。
二、部署三主三从Redis集群
首先准备六个Redis实例,目录结构可以按端口划分,例如/data/redis/7000到/data/redis/7005。每个目录下放一个redis.conf,核心配置必须开启集群模式,并指定独立的cluster-config-file。下面是一份适用于7000端口的配置模板,其他节点只需替换对应的端口和文件名。
port 7000 bind 0.0.0.0 protected-mode no daemonize yes pidfile /var/run/redis_7000.pid logfile /var/log/redis_7000.log dir /data/redis/7000 cluster-enabled yes cluster-config-file nodes-7000.conf cluster-node-timeout 5000 appendonly yes appendfilename appendonly.aof
这里需要特别留意bind和protected-mode两个配置。如果节点之间跨机器部署,bind 0.0.0.0可以让Redis监听所有网卡,但生产环境建议指定内网IP。protected-mode设为no是为了避免本地测试时被保护模式拦截,跨网络访问时也经常需要关闭。另一个容易忽视的参数是cluster-announce-ip,当Redis运行在容器或NAT环境中时,必须手动设置成其他节点可访问的IP,否则Gossip协议交换到的地址可能是容器内部地址,导致集群创建后节点间无法通信。
六个实例都启动之后,使用redis-cli的集群创建命令把它们组成一个集群。下面的命令会自动将前三个节点设为主节点,后三个节点分别作为前三个主节点的从节点。
redis-cli --cluster create 127.0.0.1:7000 127.0.0.1:7001 127.0.0.1:7002 127.0.0.1:7003 127.0.0.1:7004 127.0.0.1:7005 --cluster-replicas 1
执行后redis-cli会展示槽位分配方案,并提示输入yes确认。如果所有槽都被覆盖,输出末尾会出现[OK] All 16384 slots covered。如果中途报错,通常是因为某些节点已经存有旧数据或cluster-config-file不一致,可以先清理对应目录下的nodes文件、AOF和RDB,再重新执行创建命令。
三、验证集群数据分片与读写
创建成功后,使用-c参数连接集群中的任意一个节点。-c表示启用集群模式客户端,它会自动处理MOVED重定向。执行set命令时,如果key落到了其他主节点,客户端会跟随重定向并切换到目标节点。下面的示例中,连接的是7000,但key user:1001实际位于7002节点,客户端自动完成了跳转。
redis-cli -c -h 127.0.0.1 -p 7000 127.0.0.1:7000> set user:1001 zhangsan -> Redirected to slot [7627] located at 127.0.0.1:7002 OK 127.0.0.1:7002> get user:1001 "zhangsan"
如果不加-c参数,直接连接7000执行同样的命令,会收到MOVED错误信息,提示key所在的目标节点。开发调试时需要注意,不能只用单节点客户端去操作集群。测试槽位分布可以批量写入不同前缀的key,观察它们是否被分发到不同主节点。通过cluster slots命令可以查看每个槽区间的实际操作节点,便于验证数据是否按预期分布。
redis-cli -p 7000 cluster slots
还可以查看cluster info和cluster nodes了解集群整体状态。cluster info中的cluster_state应为ok,cluster_slots_assigned应为16384,cluster_known_nodes应为6。cluster nodes会列出每个节点的ID、角色、槽位和主从关系,用于快速定位异常节点。
四、故障转移与集群运维测试
高可用测试是部署后必须做的一环。选择一个主节点,比如7000,执行shutdown命令模拟宕机。集群会检测到该主节点失联,并在cluster-node-timeout时间后触发从节点选举。原7000的从节点会被提升为新的主节点,接管原主节点的槽。
redis-cli -p 7000 shutdown nosave
随后查看任意存活节点的cluster nodes,可以看到新的master标识出现在原从节点上。整个故障转移过程通常在几秒到十几秒内完成,期间写入可能会失败,因此生产环境需要客户端配合重试机制。如果原主节点恢复上线,它会自动成为新主节点的从节点,不会发生脑裂。
除了被动故障转移,运维中还可以主动执行cluster failover命令。在某个从节点上执行该命令,会强制进行主从切换,常用于滚动维护主节点。下面的命令在7003从节点上执行,让它接管其主节点的角色。
redis-cli -p 7003 cluster failover takeover
接管完成后,原来的主节点会降级为从节点。这种方式对业务影响较小,可以在计划内维护时使用。测试完故障转移后,建议再执行一轮读写操作,确认集群仍然可以正常服务。如果发现集群状态变为fail,需要先检查是否存在未覆盖的槽,或者是否有节点无法通信。多数情况下,网络策略和cluster-announce-ip配置是问题根源。