Redis Cluster集群部署实战:数据分片、槽位分配与高可用故障转移

发布时间:2026/10/22 4:45:59
Redis Cluster集群部署实战:数据分片、槽位分配与高可用故障转移
不废话直接上干货。这篇文章记录我在Linux服务器上部署Redis集群的完整过程。文章里不只有命令和配置还包括我对方案选型的思考、一步步执行的实操记录、以及部署过程中真实踩过的坑和最终的排查思路。如果你正准备在生产或测试环境搭建一套Redis集群这篇文章可以作为一份可落地的操作手册。1. 方案选型为什么我选择了Redis Cluster在动手部署之前先想清楚一个问题我们需要什么样的集群方案Redis的分布式方案主要有三大类分别是主从复制加哨兵、Redis Cluster官方集群、以及代理模式的中间件方案。每一种都有各自的适用场景我在实际选择时重点考虑了高可用能力、数据分片能力和运维复杂度这三项指标。先说主从加哨兵方案。这套方案的核心思路是一主多从数据从主节点同步到从节点由独立部署的哨兵进程监控主节点状态。一旦主节点发生故障哨兵会自动执行故障转移把一个从节点提升为新的主节点。这套方案的好处是架构简单Redis版本兼容性好而且支持读写分离。但它的局限性也很明显所有节点保存的是同一份数据的副本数据容量受限于单台服务器的内存无法做到横向扩展。如果业务数据量突破了单机上限这套方案就无法解决了。再说Redis Cluster官方集群方案。这是Redis作者在3.0版本推出的官方分布式方案它把数据自动分散到多个节点上每个节点只负责一部分数据。Cluster模式采用无中心架构所有节点互联互通客户端可以访问任意节点内部通过Gossip协议通信。当主节点故障时其从节点会自动提升这个过程对应用层基本透明。我最看重它的两点一是数据自动分片解决了容量瓶颈二是官方原生支持升级维护都省心。当然它也有代价比如多键操作受限、客户端必须支持Cluster协议这些我在下文会详细说明。最后是代理中间件方案。比如常见的代理层方案思路是在Redis前面加一层代理由代理负责数据路由和分片应用层连接代理就像连接一台Redis单机一样。这种方案确实可以实现分片也能在一定程度上屏蔽集群细节但需要额外部署和维护代理组件增加了链路延迟而且高可用配置也比较繁琐。在实际项目里如果数据量预估会超过单机内存又要保证高可用那官方的Redis Cluster是当前最均衡的选择。所以本篇文章统一用Redis Cluster作为主线来展开部署细节。2. 集群部署的核心原理与前置准备2.1 数据分片与槽位分配的底层逻辑Redis Cluster之所以能把数据分散到多台服务器核心机制是槽位分配。它定义了一个包含16384个槽位的逻辑空间每个key通过CRC16算法计算出一个哈希值再对16384取模得到一个固定的槽位编号。集群启动时这些槽位会被均匀地分配到各个主节点上。举个例子。假如集群有三个主节点那么一种常见的分配方式是第一个节点负责0到5460号槽位第二个节点负责5461到10922号槽位第三个节点负责10923到16383号槽位。客户端写入一个key时任一个节点接收到请求后会先计算这个key对应的槽位如果槽位不在自己负责的范围内就会返回MOVED重定向指令告诉客户端应该连接哪个节点。网上有些文章推荐使用hash tag来做强制分片这个技巧值得一提。Redis Cluster在计算槽位时允许用户指定key的一小部分作为哈希计算因子。只要把这部分用花括号包起来属于同一个用户的所有key就会落在相同的槽位上从而支持在同一节点上执行多键操作。比如{user:1001}:profile{user:1001}:orders上面这两个key的槽位都是根据user:1001计算出来的天然落在同一个节点上。这个技巧在设计缓存key时非常实用也是我做集群规划时反复提醒团队的注意事项。2.2 主从副本与故障转移的工作机制Cluster模式下的每个主节点至少需要挂一个从节点。从节点负责实时同步主节点的数据同时作为主节点宕机后的替补。当集群检测到一个主节点失联超过设定时间会启动自动故障转移流程。这里有一个关键参数需要解释cluster-node-timeout。这个参数决定了节点失联多久会被判定为故障默认值为15000毫秒。集群通过Gossip协议在节点间交换状态信息如果一个主节点在超时时间内没有响应它会被标记为疑似下线之后其他节点协同确认后该节点被标记为下线状态。如果这个主节点有从节点从节点会发起选举变为新的主节点并接管原主节点的所有槽位。这里我遇到过很多人问如果主节点和从节点刚好部署在同一台物理机上怎么办如果那台机器宕机了主备同时不可用集群就失去了高可用保障。所以生产环境一定要把主节点和从节点分散到不同的物理机或机架上这一点在规划部署拓扑时必须提前设计好。2.3 部署前的硬件资源与系统环境清单Redis Cluster对硬件的要求其实不高但官方建议六节点起步。我的推荐方案是三主三从这样既能保证数据分片又能在任何一个主节点宕机时自动完成故障转移。如果服务器资源有限最低限度是三节点一主一从的方案也就是三台机器各部署一套主从但这会弱化跨机容灾能力。部署前需要准备好操作系统层面的环境。首先确认内核版本和系统版本以常见的Linux发行版为例CentOS和Ubuntu的包管理命令不同但Redis本身是编译安装的对系统版本并不挑剔。然后需要检查是否有gcc、make编译工具链因为Redis官方没有直接提供各发行版的二进制包源码编译是最标准的方式。同时规划好端口资源。Redis Cluster节点默认使用6379端口但集群节点之间还有一条用于Gossip通信的总线端口默认是客户端端口加10000也就是集群模式下会在7379端口上监听。在云服务器或防火墙配置里这两个端口都需要放行。如果启用密码认证集群节点间也要配置相同的认证密码否则节点之间无法完成握手。2.4 软件版本选型说明我使用的是较新的Redis稳定版本比如7.0或7.2系列。Redis 7.x在集群管理命令和配置项上有一定的改进特别是对节点重启后的数据恢复效率做了优化而且默认在有密码的情况下也对cluster bus通信做了完整的认证处理。需要注意的是不同大版本之间的集群协议是兼容的但混合部署不同小版本在生产环境里并不推荐因为节点的故障检测和槽位迁移行为可能有细微差异增加排查问题的难度。还有一点Redis 6.0以后引入了ACL权限控制如果计划用ACL管理访问用户要注意集群模式下ACL用户需要保证所有节点配置一致否则客户端访问时可能出现权限校验错误。这一点我在后面的问题排查部分还会再提。3. 每台节点上的安装配置与集群组建3.1 源码编译安装Redis我用标准的三位节点拓扑来做演示三台服务器IP我分别用192.168.1.11、192.168.1.12、192.168.1.13替代。实际生产环境中请替换成你自己的内网IP或主机名。先在一台服务器上用源码编译安装Redis。CentOS系统执行下面的命令安装编译依赖yum install -y gcc make然后从官方下载Redis源码包。这里以7.0.14版本为例强烈建议到官网或镜像站下载不要用不明来源的压缩包。执行如下cd /opt wget https://download.redis.io/releases/redis-7.0.14.tar.gz tar zxvf redis-7.0.14.tar.gz cd redis-7.0.14 make -j4 make install PREFIX/usr/local/redis编译完成后Redis的可执行文件会安装到/usr/local/redis/bin目录下主要包括redis-server、redis-cli等二进制程序。为了方便调用把软链接指到/usr/local/binln -s /usr/local/redis/bin/redis-server /usr/local/bin/redis-server ln -s /usr/local/redis/bin/redis-cli /usr/local/bin/redis-cli编译过程中如果遇到内存不足导致编译中断可以减少-j后面的并行参数。另外一定检查gcc版本过老的版本可能会导致编译失败。如果报错说缺少某个头文件一般是基础依赖没装齐回看第一步的安装命令即可。3.2 配置文件的逐项解析每台节点都需要准备一个redis.conf配置文件。下面是一个适用于Cluster模式的基础配置我用注释的方式说明每一项的实际作用# 绑定内网IP生产环境要拒绝外网直连 bind 0.0.0.0 # 节点端口 port 6379 # 守护进程方式启动 daemonize yes # 进程ID文件路径 pidfile /var/run/redis_6379.pid # 日志级别和日志文件 loglevel notice logfile /var/log/redis/6379.log # RDB持久化文件保存路径和名称 dir /data/redis/data dbfilename dump-6379.rdb # 开启AOF持久化 appendonly yes appendfilename appendonly-6379.aof # 开启集群模式 cluster-enabled yes # 集群配置文件名节点之间自动维护这个文件 cluster-config-file nodes-6379.conf # 节点失联多久视为故障默认15000毫秒 cluster-node-timeout 15000 # 开启密码认证 requirepass your_strong_password # 集群总线通信密码必须与requirepass保持一致 masterauth your_strong_password这里重点强调三个点。第一cluster-enabled yes是必须打开的开关不打开这个选项后面的集群相关指令全部无法使用。第二cluster-config-file这个文件是集群自动生成的不需要手工创建集群拓扑发生变化时Redis会自动更新它。第三requirepass和masterauth必须同时配置前者是客户端访问认证后者是主从节点间复制和集群总线通信的认证很多部署时会漏掉后一个配置导致主从切换失败。创建数据目录并同步到其他两台服务器mkdir -p /data/redis/data mkdir -p /var/log/redis把同样的配置改完IP或保持0.0.0.0监听后在三台机器上分别启动redis-server /etc/redis.conf启动后先确认进程和端口状态。执行ps -ef | grep redis应该看到redis-server进程执行netstat -tlnp | grep redis应该看到6379和7379端口都在监听状态。7379就是集群总线端口当这个端口没有正常监听时后面执行节点加入集群的命令一定会失败。3.3 组建集群与分配主从角色最经典的方式是直接使用Redis自带的redis-cli --cluster create命令完成集群搭建。该命令会自动完成槽位分配和主从配置。先在三台主节点上执行创建命令redis-cli -a your_strong_password --cluster create \ 192.168.1.11:6379 192.168.1.12:6379 192.168.1.13:6379 \ --cluster-replicas 0--cluster-replicas 0表示当前先不分配从节点只是先把三主集群建起来。命令执行后redis-cli会打印槽位分配计划并向你询问是否接受该计划。确认无误后输入yes回车。如果创建成功终端会提示所有槽位分配完成集群状态为正常。如果你想一步到位在创建时直接分配从节点需要准备六台节点把三个从节点IP也加进命令redis-cli -a your_strong_password --cluster create \ 192.168.1.11:6379 192.168.1.12:6379 192.168.1.13:6379 \ 192.168.1.14:6379 192.168.1.15:6379 192.168.1.16:6379 \ --cluster-replicas 1--cluster-replicas 1意思是每个主节点配置一个从节点redis-cli会自动决定如何配对。为了验证故障转移效果我这里的演示环境是三主三从都具备的。集群创建完成后登录任意节点用cluster info查看集群状态redis-cli -a your_strong_password -c cluster info输出里重点看cluster_state:ok和cluster_known_nodes:6。如果cluster_state不是ok说明槽位没有分配完整或节点通信存在故障需要立即排查这在后面第5节会详细分析。查看每个节点负责的槽位范围redis-cli -a your_strong_password -c cluster nodes输出结果中每行代表一个节点。节点ID、IP端口、角色、负责的槽位范围、节点连接状态都在这一行里。正常状态是主节点行末尾标识为connected从节点行中带有slave字样并会列出它对应的主节点ID。3.4 集群模式客户端的读写请求验证集群搭建完成后用redis-cli测试读写。访问集群时redis-cli需要加上-c参数这个参数开启集群重定向功能当客户端访问的key不在当前节点时redis-cli会自动跟随MOVED重定向从而完成读写redis-cli -a your_strong_password -c进入交互模式后尝试写入多个key并读取192.168.1.11:6379 set user:name test - Redirected to slot [7621] located at 192.168.1.12:6379 OK 192.168.1.11:6379 get user:name - Redirected to slot [7621] located at 192.168.1.12:6379 test这个重定向输出非常直观。可以看到虽然连接入口是11号节点但user:name的槽位落在12号节点上redis-cli自动跳转完成读写。这说明数据分片已经生效三个节点在协同工作。如果不加-c参数直接连接某个节点执行getRedis会返回MOVED错误同时提示正确的节点IP。这也是判断一个客户端是否支持Cluster协议的最简单方式。4. 生产环境下集群的高可用与运维细节4.1 主从自动故障转移的实测验证集群部署完成后高可用特性必须经过实测验证不能只看文档。我的做法是人为模拟主节点宕机验证从节点是否自动晋升为新的主节点。先记录当前集群角色状态。假设192.168.1.11是主节点它的从节点是192.168.1.14。现在用shutdown命令模拟宕机redis-cli -a your_strong_password -h 192.168.1.11 -p 6379 shutdown等待十几秒后重新查看集群状态redis-cli -a your_strong_password -c cluster nodes正常情况下输出的节点列表里192.168.1.14的角色已经变成了master并且接管了原先分配给192.168.1.11的所有槽位。客户端继续读写这些槽位对应的key依然可以正常工作。这个测试流程非常关键如果从节点没有完成提升说明masterauth配置有问题或节点间心跳异常需要立即修复。故障转移完成后把宕机的节点重新启动。启动后的节点会发现自己是孤立节点没有角色同时又检测到原槽位已被其他节点接管。此时需要手动把它作为从节点加入新的主节点。方式如下redis-cli -a your_strong_password --cluster add-node \ 192.168.1.11:6379 192.168.1.14:6379 \ --cluster-slave命令里第一个IP是新加入的节点第二个IP是集群中任意一个已有节点。加--cluster-slave参数后redis-cli会随机让新节点成为某个主节点的从节点。如果我想指定它跟随192.168.1.14需要用下面的方式redis-cli -a your_strong_password --cluster add-node \ 192.168.1.11:6379 192.168.1.14:6379 \ --cluster-slave --cluster-master-id 新的主节点ID--cluster-master-id后面跟上目标主节点的ID可以在cluster nodes输出中查询到。这样能精确控制拓扑结构避免从节点挂到不想挂的主节点下。4.2 槽位迁移与节点扩容的实操方法当业务增长单集群容量出现瓶颈时就需要扩容。扩容的本质是加入新节点并迁移部分槽位过去让数据分布更均匀。整个过程可以在线完成不需要停服。先按第3.1节的方法安装好新Redis实例并启动确保cluster-enabled yes。然后执行添加节点命令把新节点加入现有集群。假设新节点是192.168.1.17:6379要从当前集群加入redis-cli -a your_strong_password --cluster add-node \ 192.168.1.17:6379 192.168.1.11:6379如果想让新节点作为从节点加入同样加--cluster-slave参数。新节点加入后最初不负责任何槽位需要手动把其他节点的部分槽位移过去。执行重分配命令redis-cli -a your_strong_password --cluster reshard \ 192.168.1.11:6379这个命令是交互式的会依次询问迁移多少个槽位、要迁移到哪个节点ID、以及从哪些节点搬出槽位。假设要向新节点迁移1000个槽位交互过程中填1000然后填新节点的ID最后all表示从所有现有主节点平均抽取。确认计划后输入yes执行迁移。迁移过程中Redis会把相关key数据异步迁移到目标节点。这个过程中客户端几乎无感知但如果迁移的key量非常大迁移期间batch命令会占用部分CPU和网络带宽。我建议在业务低峰期操作并时刻关注redis日志。迁移完成后再次查看cluster nodes确认各节点槽位数量。扩容过程中有一个典型注意事项新加入的主节点初始没有从节点生产环境必须给它补一个从节点否则该节点如果宕机会直接导致部分槽位不可用。4.3 数据持久化与备份恢复的坑Redis Cluster模式下数据持久化策略与单机模式没有本质区别RDB和AOF依然可以使用只是每个节点独立保存自己的数据。生产环境里我推荐同时开启RDB和AOF在dir指明的数据目录下两种文件会同时存在。这里有个非常现实的坑我在多个环境都踩到过集群节点数据目录里的nodes-6379.conf文件如果被删除或改动重启节点时Redis会认为它是一个全新的空节点导致集群ID变化旧的配置全部失效。这个文件是Redis自动维护的做备份恢复时最稳妥的姿势是把整个数据目录完整打包包括RDB、AOF和nodes.conf三个文件全部一起备份。绝不能只拷贝RDB文件。做集群备份还有一个简单高效的办法直接在某个从节点执行redis-cli --rdb或者使用BGSAVE触发持久化然后拷贝RDB文件。因为从节点数据与主节点完全一致这样备份既不影响业务读写又能拿到完整的数据快照。AOF重写机制在集群下同样适用后台执行BGREWRITEAOF可以压缩AOF日志体积。4.4 运维监控与预警要点集群部署结束只是开始真正的挑战在线上长期稳定运行。我整理了一套基础的监控清单覆盖了节点状态、内存、命令延迟和持久化情况。节点可用性通过cluster info持续检查cluster_state字段只要不是ok就要立刻告警。槽位完整性定期执行cluster nodes确保节点总数、主从关系符合预期不能出现槽位无人负责的情况。内存使用率每个节点的used_memory与maxmemory比值是需要重点关注的内存预警指标。延迟趋势用redis-cli的--latency参数周期性采样观察命令处理延迟是否有持续上涨的趋势。持久化状态关注日志中是否有Background saving error或AOF rewrite scheduled异常信息。有条件的团队建议直接在监控系统中接入Prometheus的redis_exporter把上述指标全部采集并配置告警规则比自己写脚本轮询要稳妥得多。5. 常见问题与排查技巧实录5.1 集群状态不是ok怎么办cluster_state:nok是最常见的集群异常状态原因几乎都是槽位不完整或有节点失联。第一步是登录任意节点执行redis-cli -a 密码 cluster nodes重点看两部分节点列表里是否有disconnected状态以及每个主节点对应槽位的分配情况是否覆盖0到16383的全部范围。如果是有节点失联先检查网络连通性。在故障节点和其他节点之间用redis-cli -p 6379 ping验证基础连通性再用telnet检查7379集群总线端口是否开放。很多云环境只开放了业务端口漏开了集群总线端口导致节点间通信失败。如果是槽位分配不完整比如某些槽位显示为无主状态可以考虑把缺失的槽位重新分配。这里有个小技巧可以先备份数据再用redis-cli --cluster fix让工具自动尝试修复槽位。这个命令适用于槽位分配异常但不严重的情况如果是大面积槽位丢失老老实实规划迁移计划不要盲目执行fix。5.2 MOVED重定向和CLUSTERDOWN的判定这两种错误信息在客户端访问集群时高概率会遇到含义完全不一样排障思路也不同。MOVED表示数据不在当前节点客户端需要根据返回提示连接到正确节点重新发起请求。这是Cluster模式下的正常机制只要客户端库支持Cluster协议会自动处理不会报错。如果你用的是普通单机模式客户端连接到集群就会出现大量MOVED报错。解决办法是更换客户端库为支持Cluster模式的版本或者在连接参数中启用集群模式。CLUSTERDOWN表示整个集群处于不可服务状态原因一般是槽位不完全没有节点负责所有槽位。比如一个主节点宕机且它的从节点没有完成晋升就会导致该主节点负责的槽位暂时不可用。此时优先检查故障转移是否执行成功如果失败人工介入完成从节点晋升。处理完槽位后cluster_state会自动恢复为ok客户端无需重启。还有一个容易忽略的原因写入多键操作时如果多个key不在同一槽位Redis Cluster会直接返回CROSSSLOT错误。看到这个错误不要慌这不是架构故障而是业务代码使用了跨节点的多键操作。要么修改业务逻辑分批处理要么用hash tag把相关key固定到同一槽位。5.3 主从切换后连接失败问题故障转移完成后客户端可能短暂报连接异常。这通常是因为客户端本地缓存的集群拓扑信息还指向旧主节点。支持Cluster协议的客户端内部会缓存节点映射表当它收到MOVED重定向后会更新缓存。如果客户端短期内频繁连接失败可以考虑在连接配置中调低集群拓扑刷新时间或者手动重建连接。我在生产上遇到过一种更隐蔽的情况Redis配置了ACL用户但故障转移完成后从节点明明晋升为主节点了客户端仍报权限错误。排查后发现是ACL规则没有在所有节点上保持一致。集群模式要求每个节点的ACL配置完全一致开启密码认证和ACL时主从、节点间使用的账户权限必须同步配置到位。后面我改用统一管理配置文件分发的方式才彻底解决了权限漂移的问题。5.4 Docker或容器化部署时的额外注意如果是在容器环境里部署Redis Cluster建议把cluster-announce-ip和cluster-announce-port这两个参数配置完整。容器网络环境复杂节点之间通过内部IP访问但客户端如果通过外部IP访问容器外的节点无法通过内部IP完成重定向。因此需要显式通告一个客户端可访问的IP和端口。cluster-announce-port还有一个容易纠结的地方它配置的是客户端访问的端口不是集群总线端口。总线端口的通告地址需要单独配置cluster-announce-bus-port。很多容器化场景里节点能正常加入集群但客户端无法读写排查到最后都是这几个通告参数没配对。容器化部署还要注意数据卷的问题。Redis的数据目录和配置目录必须挂载持久化卷不然容器重启后数据丢失节点ID变化集群直接四分五裂。如果环境里用的是Kubernetes建议使用StatefulSet管理集群节点保证稳定网络标识和持久化存储。6. 部署过程中的经验总结Redis Cluster部署做完之后我最大的体会是真正的难点从来不是执行那几条命令而是对集群原理的理解和对细节的把控。从槽位分配到主从切换从端口规划到数据备份每一个环节都可能因为一个参数失误或者一处网络限制而崩溃。建议第一次做集群部署的读者先在测试环境把所有故障场景完整演练一遍杀掉主节点看从节点是否晋升、迁移槽位看数据是否完整、重启整个集群看持久化文件是否能顺利恢复。这些演练会让后续生产维护变得坦然很多因为最坏的情况你已经见过了并且知道怎么解决。另外集群搭建完成后务必把所有配置文件和操作命令沉淀为自动化脚本或者文档模板。很多团队第一次部署很顺利但三个月后扩容或节点替换时发现操作手法已经记不清了。我个人的做法是把这些操作整理成内部运维手册包括每个节点的IP、角色、端口、数据目录、备份策略这样即使出现人员变动新接手的人也能迅速上手。