ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

Redis 7集群搭建实战:从节点规划到故障转移全解析

Redis 7集群搭建实战:从节点规划到故障转移全解析 说到 Redis 7 集群搭建我估计不少朋友已经踩过一轮坑了。网上教程确实多但要么停留在单个实例的伪集群要么只贴命令不讲为什么真到自己动手把多机环境拉起来还是会卡在节点握手、槽位分配、故障转移这些细节点上。这篇文章不是把官方文档搬过来而是按我实际搭建的完整流程走一遍从环境准备、编译安装、配置项逐条拆解到集群初始化、数据分片原理再到扩容缩容、常见故障排查尽量把每一步背后的逻辑说清楚方便你照着操作也能在出了问题时自己定位。1. 搭建前的关键决策到底选哪种集群方案1.1 主从复制、哨兵和 Cluster 三者的本质区别很多人在搭集群之前其实并没有想清楚自己到底需要什么。主从复制只是把数据同步到多个节点解决的是读压力和单点故障但它没有自动故障转移主节点挂了需要人工介入。Redis Sentinel 在主从基础上加了监控和自动切换能保证高可用但它存的数据量依然受单机内存上限约束写能力也只有一个主节点能扛。而 Redis Cluster 从一开始就是为“水平扩展”设计的它把 16384 个哈希槽分散到多个主节点上每个主节点只负责一部分数据配合副本节点实现高可用容量和写性能都能横向扩展。如果你只是需要读写分离和高可用主从加哨兵就够用如果你对未来数据量心里没底或者已经感觉到单机内存成为瓶颈那直接上 Cluster 是对的。说实话Cluster 的运维复杂度比哨兵高不少节点间通信、槽位迁移、重定向机制都需要额外理解和维护但它换来的是真正的横向扩容能力。当年我在生产环境从哨兵模式迁移到 Cluster就是因为业务增长太快单机 64G 内存完全扛不住这个迁移过程后面你也迟早会遇到。1.2 节点规划与端口分配这些细节决定了你能不能少走弯路规划集群时最基础但也最容易被忽略的是端口规划。Redis Cluster 里每个节点除了对外服务的业务端口比如 7000还会自动占用一个集群总线端口也就是端口加 10000 这个固定偏移量。也就是说如果对外端口是 7000那么节点还会监听 17000 用于节点间的 gossip 通信、故障检测和配置传播。这个端口很容易在配置防火墙安全组时被漏掉一旦漏掉节点之间就会一直处于握手失败或 PFAIL 状态集群看起来好像建成了实际上根本不稳定。我习惯的规划方式是这样的假设两台物理机每台起三个实例对外端口用 7000 到 7002 和 7003 到 7005两台机器的 IP 分别记为 192.168.1.101 和 192.168.1.102。每个实例有自己的独立数据目录、日志目录和配置文件好处是后面单独扩容、替换节点时互不影响。从节点尽量分布在不同的物理机上比如主节点 7000 在机器 A 上它的从节点 7003 放在机器 B 上这样即使整台机器断电数据也不丢服务也能自动切换。具体的角色分配和目录我会在后面章节里给出一张表方便你直接对照着抄。2. 环境准备与 Redis 7 编译安装2.1 系统依赖与内核参数调整这里以常见的 RHEL/CentOS 系系统为例其实 Debian/Ubuntu 的逻辑也差不多。先把编译工具链装上Redis 7 编译需要 gcc、make如果你的系统最小化安装过大概率缺这两个。另外如果你要用到 TLS 特性还需要 openssl-devel。命令很简单但建议一次装全避免编译到一半缺头文件又重新来。yum install -y gcc gcc-c make装完编译器之后我强烈建议调整两个内核参数这一步很多人会忽略。第一个是vm.overcommit_memoryRedis 在生成 RDB 快照或执行 BGSAVE 时会 fork 子进程即使 Redis 自己的内存使用量没超过物理内存内核也有可能判定内存申请失败而拒绝 fork。你可以先直接执行下面三条命令来临时调试确认没问题后再写入/etc/sysctl.conf和开机自启脚本里。sysctl -w vm.overcommit_memory1 echo never /sys/kernel/mm/transparent_hugepage/enabled sysctl -w net.core.somaxconn1024vm.overcommit_memory1表示内核不检查内存申请是否真的够用这能很大概率避免 fork 失败的问题。transparent_hugepage也就是透明大页它对 Redis 这种内存访问密集型的应用非常不友好关掉可以减少延迟抖动。net.core.somaxconn则是提高 TCP 连接队列上限应对高并发连接时出现的 backlog 不足警告。这些参数不调整不会导致集群搭不起来但运行一段时间后各种诡异的性能问题就会冒出来。2.2 下载编译安装 Redis 7接下来下载 Redis 7 的稳定版本。建议从官网或 GitHub 的 releases 页面获取我这里以 7.2.5 为例。下载后先确认一下 tarball 的完整性可以下载对应的.sha256文件或使用sha256sum自己核对避免拿到损坏的包浪费时间。wget https://download.redis.io/releases/redis-7.2.5.tar.gz tar xzf redis-7.2.5.tar.gz cd redis-7.2.5 make -j$(nproc) make install PREFIX/usr/local/redis编译时开-j$(nproc)能明显缩短时间四核机器实测大概一分钟左右就能编完。编译过程中如果看到 jemalloc、openssl 相关的输出是 Redis 在编译内置的依赖库属于正常现象。安装到/usr/local/redis以后可执行文件会出现在/usr/local/redis/bin目录下里面至少会有redis-server、redis-cli、redis-check-aof、redis-check-rdb、redis-sentinel等工具。顺便说一句如果你需要在 Windows 环境下解压 tar 包后传到 Linux 再解压遇到中文文件名乱码一般不是 Redis 的问题而是 Windows 上的压缩工具没有按 UTF-8 编码打包用系统的 tar 重新打包或者在 Linux 下解压就能避免。这和 Redis 安装本身关系不大但很多初学者会把时间浪费在这类环境问题上留意一下能省不少事。3. 集群配置文件的逐项要点3.1 目录结构准备好后续维护少操心我个人的习惯是先把目录结构准备好再动手改配置。这里假设我的安装路径为/usr/local/redis数据目录统一放/data/redis每个实例一个子目录日志也放在各自的目录里。创建一个集群需要六个实例目录规划如下实例端口对外端口集群总线端口数据目录日志文件物理机7000700017000/data/redis/7000/data/redis/7000/redis.log192.168.1.1017001700117001/data/redis/7001/data/redis/7001/redis.log192.168.1.1017002700217002/data/redis/7002/data/redis/7002/redis.log192.168.1.1017003700317003/data/redis/7003/data/redis/7003/redis.log192.168.1.1027004700417004/data/redis/7004/data/redis/7004/redis.log192.168.1.1027005700517005/data/redis/7005/data/redis/7005/redis.log192.168.1.102创建目录mkdir -p /data/redis/{7000,7001,7002,7003,7004,7005}有人喜欢把所有配置写在一个文件里用不同的port启动多个实例。理论上可以但排查问题时很容易分不清当前操作的是哪个实例。独立目录加独立配置文件的思路后面不管是看日志、备份数据还是迁移节点都会非常省心。3.2 配置文件逐条详解不只是把开关打开Minimal 配置其实很简单核心就是开启 cluster 模式、指定端口和数据目录。但生产环境如果只开这几个开关后面大概率会遇到一堆问题。这个了看一个完整的配置文件示例以 7000 端口为例bind 0.0.0.0 protected-mode no port 7000 daemonize yes pidfile /var/run/redis_7000.pid logfile /data/redis/7000/redis.log dir /data/redis/7000 appendonly yes appendfilename appendonly.aof auto-aof-rewrite-percentage 100 auto-aof-rewrite-min-size 64mb cluster-enabled yes cluster-config-file nodes-7000.conf cluster-node-timeout 15000 cluster-require-full-coverage no这里每一条都值得展开说。bind 0.0.0.0表示监听所有网卡如果机器有多块网卡建议改成内网 IP避免 Redis 端口暴露到不必要的网络区域。protected-mode no是因为集群节点之间、客户端与节点之间都可能需要直连默认的 protected-mode 只允许本机访问不关掉的话从其他机器连过来会被拒绝但这个开关要结合防火墙来使用千万别裸奔在公网环境。daemonize yes让 Redis 以守护进程方式运行配合pidfile可以在运维脚本里方便地做 kill、启停。如果用的是 systemd 管理可以改成daemonize no配合supervised systemd这里为了演示简单先用 daemonize。appendonly yes在 Redis 7 中默认就是开启的但我还是建议显式写出来。Redis 7 开始 AOF 机制升级为多部分文件格式会在 data 目录下生成 base 文件、incr 文件和 manifest 清单文件跟老版本只有一个 appendonly.aof 的行为有所不同。如果你在线上见过appendonly.aof.1.base.rdb、appendonly.aof.1.incr.aof之类的文件别慌那就是 Redis 7 的新 AOF 结构。最关键的是 cluster 相关配置cluster-enabled yes这一行决定实例是否以集群模式运行。cluster-config-file nodes-7000.conf这个文件由 Redis 自己维护不需要手动创建。节点启动后它会把自己知道的集群节点信息、槽位分配情况、节点状态写入这个文件。注意如果这个文件残留了上一次集群的信息重新搭建集群时很可能报 “Node is not empty” 或 “Slot already busy” 的错误所以每次做实验时记得清理这些文件。cluster-node-timeout 15000节点超时时间单位毫秒。主节点超过这个时间没有响应从节点就开始发起选举。这个值太短容易因为网络抖动误判故障太长则故障自动切换会很慢。我一般设 15 秒左右。cluster-require-full-coverage no这个参数值得重点解释。默认值是 yes表示只有所有 16384 个槽都被节点服务时集群才对外提供服务。如果某个主节点挂了它负责的槽位变成未覆盖状态整个集群就会拒绝所有读写请求。生产环境我一般会设为 no这样即使部分槽位不可用其他槽位的数据读写还能继续但这意味着不在线的那部分数据对客户端来说会报错你需要结合业务容忍度来判断。重要系统里最好还是保留 yes宁可让请求失败也不要在故障时返回不完整的数据。3.3 从节点和密码认证生产环境绕不开的两个点上面的配置是以 7000 主节点为例的。从节点配置其实几乎一样唯一的区别是你可以指定它从哪个主节点复制但实际上 Redis Cluster 创建集群时通过--cluster-replicas 1参数会自动分配主从关系不需要在配置文件里手写replicaof这点和主从复制模式的配置方式很不一样。所以配置文件基本可以照抄只要把端口、pidfile、logfile、dir 对应的数字改成实际端口即可。如果你的业务要求访问必须带密码那需要在每个配置文件中额外加上两行注意一定是两条requirepass yourstrongpassword masterauth yourstrongpasswordrequirepass是客户端连接时需要的密码masterauth是主从之间进行复制时的认证密码。从节点要访问主节点去拉取数据必须由主节点进行身份认证所以这两条要同时设置。在集群模式下配置文件里加了密码之后后续用redis-cli创建集群和检查集群时都要带上密码参数否则会提示认证失败。4. 实例启动与集群初始化4.1 把六个节点全部启动起来配置写好后逐个启动。手动启动的方法是一个一个执行redis-server例如/usr/local/redis/bin/redis-server /usr/local/redis/conf/redis-7000.conf /usr/local/redis/bin/redis-server /usr/local/redis/conf/redis-7001.conf如果你配置了两台机器那么 7000 到 7002 在机器 A 启动7003 到 7005 在机器 B 启动。启动完成后用ps -ef | grep redis或redis-cli -p 7000 ping检查一下能收到 PONG 就说明基本正常。这时集群还没有建立每个节点都只知道自己是孤立的 cluster 节点可以用redis-cli -p 7000 cluster info看一下状态大概率cluster_state:fail、cluster_slots_assigned:0这是正常的因为槽位还没分配。启动阶段容易踩的坑是端口没监听成功。用netstat -lntp或ss -lntp检查 7000 到 7005 端口同时确认 17000 到 17005 也被监听。如果端口没起来八成是配置文件里的bind或protected-mode不对或者端口被占用。注意cluster-config-file指向的目录必须可写否则节点启动时无法生成 nodes 配置文件也会导致启动失败。4.2 一键创建集群槽位分配和主从关系自动完成Redis 5 之前创建集群要额外装 ruby 的redis-trib.rb5.0 之后直接用redis-cli --cluster子命令就可以完成Redis 7 同样如此。假设两台机器 IP 已确定推荐用下面的方式把 192.168.1.101 上的 7000 到 7002 和 192.168.1.102 上的 7003 到 7005 联合起来/usr/local/redis/bin/redis-cli --cluster create \ 192.168.1.101:7000 192.168.1.101:7001 192.168.1.101:7002 \ 192.168.1.102:7003 192.168.1.102:7004 192.168.1.102:7005 \ --cluster-replicas 1--cluster-replicas 1表示每个主节点配一个从节点。执行后redis-cli 会自动计算槽位分配方案一般会把 0 到 5460 给第一个主节点5461 到 10922 给第二个10923 到 16383 给第三个然后为每个主节点选择副本。它会打印出完整的分配计划并让你确认交互式输入yes即可确认。如果你配置了密码要在命令里加上-a yourstrongpassword。不加的话创建过程中会因为无法认证而失败错误信息一般比较明显比如ERR Client sent AUTH, but no password is set。注意确认密码的两个方向既要确认客户端认证也要确认主从之间的 masterauth 配好了不然后面复制链路起不来。4.3 验证集群状态三步确认真的没问题创建完成后不要急着写业务先做三步验证。第一步看集群概览/usr/local/redis/bin/redis-cli -p 7000 cluster info重点看cluster_state:ok、cluster_slots_assigned:16384、cluster_known_nodes:6这几个关键行。只要cluster_state不是 ok后面读写请求很可能直接报CLUSTERDOWN。第二步看节点拓扑和主从关系/usr/local/redis/bin/redis-cli -p 7000 cluster nodes | sort -k9输出中每行代表一个节点包含节点 ID、IP 端口、角色、从属关系等。看到master后面跟着slave节点并且每个 master 都有对应的 slave说明主从分配正常。如果某个节点后面一直标着disconnected或fail?就要回到网络层面排查。第三步用集群自带的检查命令做一次全面体检/usr/local/redis/bin/redis-cli --cluster check 192.168.1.101:7000这个命令会检查槽位覆盖情况、节点间连接状态、从节点复制是否正常能一次性把大部分常见问题暴露出来。如果输出里有All 16384 slots covered这种字样就可以放心了。验证完毕后我习惯顺手存一个数据测试一下跨节点读写/usr/local/redis/bin/redis-cli -c -p 7000 set greeting hello cluster /usr/local/redis/bin/redis-cli -c -p 7000 get greeting-c选项让客户端自动处理 MOVED 重定向如果键被分到其他节点-c模式会帮你跳转这样能确认槽位分配和数据定位逻辑是否正常。5. 集群运行原理与数据分片机制5.1 哈希槽与 CRC16为什么有时候跳到另一个节点Redis Cluster 的数据分片不像传统一致性哈希那样用哈希环而是采用固定 16384 个哈希槽。每个 key 通过 CRC16 算法算出一个 16 位的值然后对 16384 取模得到槽号。集群创建时这 16384 个槽均匀分给各个主节点客户端写入某个 key 时Redis 会计算它属于哪个槽然后由该槽所在的主节点提供服务。写代码时你可能会遇到一个现象用redis-cli不带-c参数访问某个节点的 key在一些情况下会返回MOVED错误。这不是故障而是集群的正常机制——节点发现这个 key 应该由另一个节点服务时会返回MOVED重定向信息告诉客户端去访问正确的节点。所以生产环境用客户端时一定要选择支持集群模式的客户端比如 Java 的 Lettuce、Jedis Cluster、Go 的 go-redis、Python 的 redis-py-cluster它们会在内部自动处理重定向和路由表更新不需要你手动拼节点地址。关于为什么是 16384 而不是 65536Redis 作者在社区里有解释16384 个槽位在节点间的心跳包中可以用 2KB 的位图来表示节点数量在千个以内时非常轻量如果扩大到 65536每个心跳包会多出 8KB 的开销并且节点数量很多时迁移复杂度也会非线性增长。16384 是在“足够细的分片”和“通信开销合理”之间做的一个折中。5.2 集群总线、gossip 心跳与故障转移集群节点之间通过集群总线通信也就是业务端口加 10000 的那个端口。这部分的流量和正常客户端访问是分离的专门用来传播节点状态、槽位分配、主从变更等元数据。每个节点不是把所有信息都广播给所有人而是用 gossip 协议随机挑几个节点交换状态最后整个集群的状态会趋于一致。故障检测和自动切换走向成熟要经历几个状态。首先某个主节点如果超过cluster-node-timeout时间没有心跳会被其他节点标记为 PFAIL也就是疑似下线。如果集群中多个节点都认为它 PFAIL并且这个信息通过 gossip 传播开就会升级为 FAIL 状态。之后这个失败主节点的从节点会发起故障转移选举机制基于 Raft 算法从节点得到大多数节点投票后提升为新的主节点并接管原主节点负责的哈希槽。这个过程中有几个关键细节一是从节点选举时要求原主节点已经 FAIL而且必须等待一段随机时间避免多个从节点同时争抢二是选举成功后新主节点会广播配置纪元集群里其他节点会更新自己的视图。因此一台物理机宕机时只要每个主节点都有健康的从节点业务就能在十几秒内自动恢复这就是 Cluster 高可用的核心能力。5.3 多 key 操作与 hash tag别让你的事务和 Lua 脚本失效集群模式下有个限制跨槽位的多 key 操作是不支持的。比如在 Redis 里执行MGET key1 key2如果key1和key2算出的槽位不同在集群模式下会直接报错。如果业务确实需要这种联合查询就得用 hash tag 这个机制。hash tag 的用法是在 key 中加上花括号CRC16 计算槽号时只对花括号内的子串进行计算。比如{user:1001}:name和{user:1001}:age虽然 key 字符串不同但因为花括号里的内容都是user:1001它们会落在同一个槽位上从而支持多 key 操作、事务和 Lua 脚本。这个设计非常实用但也容易用错。要注意的是花括号内没有内容比如{}:name那 Redis 还是会对整个 key 做 CRC16导致分片不符合预期。另外hash tag 会让某些 key 集中在少数几个槽位上如果所有热点 key 都放在了同一个 tag 里会导致数据倾斜节点之间内存和流量不均。所以设计 tag 时要考虑业务能否接受单槽数据量上限。6. 扩容、缩容与在线迁移6.1 动态增加主节点先加节点再迁移槽位集群搭建不是一锤子买卖业务增长后免不了要扩容。Redis Cluster 支持在线增加节点整个过程不用停服务。假设你要将一台新机器 192.168.1.103 上的 7006 实例加入集群先用和之前一样的配置方式启动一个 cluster-enabled 的实例然后执行/usr/local/redis/bin/redis-cli --cluster add-node 192.168.1.103:7006 192.168.1.101:7000后面的192.168.1.101:7000表示让集群里任意一个现有节点作为联系人推荐用当前任意的 master 或任意节点都可以。新节点加入后它暂时是一?个空主节点不负责任何槽位。接着需要把原有节点的部分槽位迁移给它/usr/local/redis/bin/redis-cli --cluster reshard 192.168.1.101:7000交互式命令会问你几个问题要迁移多少个槽、接收槽的节点 ID 是什么、从哪些源节点迁出槽。如果你想自动化可以直接用非交互方式/usr/local/redis/bin/redis-cli --cluster reshard 192.168.1.101:7000 \ --cluster-from source_node_id \ --cluster-to target_node_id \ --cluster-slots 2048 \ --cluster-yes这里--cluster-slots 2048表示迁移 2048 个槽你也可以迁移 4096 或 5461比例看业务压力。迁移过程中Redis 会先把槽内的数据从源节点导出再导入到目标节点期间对客户端来说 key 可能短暂处于 ASK 状态。支持集群模式的客户端会自动处理 ASK 重定向所以一般不需要停机。迁移结束后可以用cluster info和--cluster check重新确认槽位分配是否健康。6.2 动态增加从节点给某个主节点加副本如果你发现某个主节点的压力特别大或者集群里某个主节点没有从节点可以单独给它加一个从节点/usr/local/redis/bin/redis-cli --cluster add-node 192.168.1.103:7007 192.168.1.101:7000 \ --cluster-slave --cluster-master-id master_node_id--cluster-slave表示新节点以从节点身份加入--cluster-master-id指定它的主节点 ID。执行后这个新节点会立刻向主节点发起全量同步把数据拉取过来然后持续保持复制。如果集群里还有体量较小的主节点也可以用这种方式针对性地补齐副本降低单点风险。6.3 缩容与删除节点别忘了先迁走数据缩容比扩容要小心一些。如果你要下线某个主节点不能直接del-node因为它身上还有槽位和数据。正确的操作是先用reshard把它负责的槽位移交给其他节点等它变成一个真正意义上的空节点再执行删除命令。/usr/local/redis/bin/redis-cli --cluster del-node 192.168.1.101:7000 node_id如果节点上还有槽位命令会直接报错提示Node has slots。所以删节点的顺序一定是先迁移槽位再下发删除命令。删除从节点就简单多了只要它已经没有复制关系直接 del-node 即可。还有一个细节集群里如果因为多次增减节点留下了孤儿节点内存和连接资源会被浪费建议定期用--cluster check检查一下节点状态和主从关系。7. 常见问题与排查技巧实录7.1 “Node is not empty”与残留配置导致集群创建失败这是搭建时非常常见的问题尤其是中断过一次创建流程之后。原因一般是节点的dir数据目录下已经存在appendonly.aof、dump.rdb等数据文件或者nodes-*.conf里已经记录了旧的集群信息。Redis 看到节点里已经有槽位或数据就会拒绝加入新集群。处理方法按顺序来先停掉 redis-server删除该端口目录下的nodes-*.conf同时清掉数据文件或者把目录整个清空。如果不想删数据也可以用redis-cli --cluster fix修复但实验环境下建议直接清空。还有一个命令是redis-cli -p 7000 cluster reset它会重置节点的槽位和集群状态但数据文件依旧可能存在所以最稳妥的办法还是确认目录干净之后再重新创建。7.2 节点一直 PFAIL/disconnected大概率是集群总线端口不通集群创建成功后过一段时间用cluster nodes查看如果某个节点状态一直显示disconnected或者从 PFAIL 转成 FAIL但客户端访问其他节点都正常那八成是节点之间的业务端口 10000的集群总线端口被防火墙、安全组拦截了。很多人只放了 7000 到 7005却忘了放 17000 到 17005节点之间无法交换心跳元数据故障检测自然无法正常收敛。这类问题排查时先ping看通不通再用telnet 192.168.1.102 17003测一下端口通不通通不了就检查防火墙规则和安全组。别一上来就重启节点很多时候重启完还是同样的状态问题在网络层面。7.3 CLUSTERDOWN 与 cluster_require_full_coverage 的取舍集群创建好以后某个主节点宕机如果你设置了cluster-require-full-coverage yes这时整个集群都会进入只读或直接拒绝服务的状态客户端报CLUSTERDOWN Hash slot not served。这是默认保护机制为了防止读到不完整的数据。但我处理线上问题时会更倾向把这个参数设成 no然后依赖业务侧对错误进行降级处理。前提是你得观察业务是否接受部分读写失败例如某些非核心功能可以容忍短时不可用而核心账务类系统则不建议。如果你当前已经因为主节点故障导致整个集群不可用临时处理办法是先把没挂的主节点对应的从节点提升上来或者手动把宕机主节点的槽位标记为已迁移再用CLUSTER FAILOVER或redis-cli --cluster fix修复。修复前一定要搞清楚故障根因不然就算集群恢复了过一阵又会再次出问题。7.4 客户端大量 MOVED 重定向路由缓存没跟上有时候集群运维操作做完了比如 reshard 或节点变更但客户端业务依然报大批量MOVED错误。这是因为部分客户端对路由表的缓存是懒更新的只有当它访问到某个节点并收到MOVED响应时才会更新本地缓存。正常的集群客户端会自己处理这个问题但如果你的客户端没有开启集群模式或者你用的是普通连接池那就会频繁遇到这种情况看起来像是“数据丢了”。遇到这类问题先确认代码里连接 Redis 的地址是否配置成集群模式。以 Java 为例Lettuce 要使用RedisClusterClientJedis 要使用JedisCluster以 Python 为例要使用redis.cluster.RedisCluster。如果你只是用一个普通的redis.Redis(host, port)去连集群跨槽访问必然出错。7.5 常见问题速查表现象可能原因排查思路创建集群报 “Slot already busy”nodes.conf 或数据目录残留清空节点数据执行 cluster reset 或删目录某个节点一直 PFAIL集群总线端口不通放行 port10000 端口检查防火墙读写报 CLUSTERDOWN有槽位未覆盖或主节点宕机恢复故障节点或调整 require-full-coverage跨节点访问报 MOVED客户端没启用集群模式使用支持集群的客户端并正确配置主从复制一直失败masterauth 未配置或密码不一致确认 requirepass 与 masterauth 一致迁移槽位后部分 key 访问失败迁移过程中客户端 ASK 重定向处理不当使用支持 ASK 的集群客户端重试机制集群节点数增多但槽位分布不均reshard 未执行或执行不完整用 reshard 重新平衡再用 check 验证7.6 一些运维心得与监控建议集群搭建起来只是第一步运行期维护才是重头戏。建议把内存使用率、连接数、慢查询日志、主从同步延迟、槽位迁移状态这几个指标纳入监控。Redis Cluster 提供了cluster info、cluster nodes这些命令可以定时采集并做阈值告警比如cluster_state不是 ok、主节点数量变动、fail 节点数量增加都要立刻告警。还有一个容易忽略的点日志和数据的磁盘空间。Redis 7 的 AOF 多部分文件会让文件数量变多如果dir满了RDB 快照或 AOF 写入都会失败这时候数据其实是带病运行的。我吃过这个亏当时集群看起来正常实际上某个节点的 AOF 已经停了很久后面主从切换后用恢复文件才发现数据落后了一大截。所以磁盘空间监控一定要配置好建议每天检查df -h。动集群操作之前最好先做备份。Redis Cluster 的备份思路不是整个集群快照而是对每个主节点做 BGSAVE 或把 AOF 拷贝出来。不要只备份一个节点因为每个节点只有一部分数据多个节点的备份组合起来才是完整数据集。恢复时把每个节点的数据放到对应目录再按原来的拓扑启动集群会自动重新构建元数据。我个人在多次操作中逐渐养成的习惯是生产环境动手前先在测试集群里把同样的操作完整走一遍。比如 reshard、add-node、failover这些操作在测试环境验证过到生产环境执行时心里就有底了。集群这种分布式系统最怕的不是原理复杂而是某一个细节被忽视导致全链路抖动。把细节和习惯固化下来比收藏多少教程都管用。
返回列表