做后端开发和运维这些年,我最大的感受是:Redis 集群这个话题,属于“看着资料不少,真上手到处是坑”的类型。很多团队一开始用单机 Redis,等流量上来以后,内存不够、主从切换不灵活、扩容要靠改代码重连,这些问题一个个冒出来,于是把 Redis 从单机迁到集群模式几乎成了必经之路。这篇内容我打算以一个老运维的视角,完整复盘 Linux 环境下从零部署一套 Redis 集群的整个过程,覆盖版本选型、环境准备、配置编写、创建集群、故障切换演练、扩容缩容以及高频排障。不管你是刚接触 Redis 的开发者,还是正在做架构升级的运维,按着这套流程走一遍,应该能少踩不少坑。
1. 为什么要用 Redis 集群:从单机到集群的必然路径
1.1 单机 Redis 的瓶颈到底在哪
单机 Redis 的问题,本质上可以归结为三个维度:容量、可用性和性能。
先说容量。一台服务器的物理内存终归是有限的,Redis 作为基于内存的数据存储,数据量一旦超过服务器内存能承受的上限,系统就会变得极其不稳定。你当然可以通过配置 maxmemory 限制 Redis 能用的内存,但限制了之后,新增数据就只能走淘汰策略,对业务来说这和丢数据差不了太多。另一个办法是换更大内存的服务器,可 512GB 内存的机器价格翻好几倍,而且单机内存规格总有天花板,业务增长期靠换机器不是可持续发展的方案。
再说可用性。单机 Redis 一旦宕机,所有依赖缓存的请求会直接打到数据库,数据库抗不住就会引发连锁故障。哪怕你手动做了主从复制,主节点挂掉之后,还需要人工去执行 SLAVEOF NO ONE 把从节点提升为主节点,这个过程耗时越长,业务受影响的时间就越长。凌晨三点被电话叫起来手工切换,经历过的人都懂。
最后是性能。Redis 的命令执行是单线程的,虽然 Redis 6.0 之后引入了 IO 多线程来处理网络读写,但核心命令执行仍然是单线程模型。单实例的处理能力受限于单核 CPU,如果业务请求量巨大,单个 Redis 实例会慢慢逼近性能天花板。而且随着数据量增大,RDB 持久化时的 fork 耗时会变长,也有造成服务卡顿的风险。
1.2 集群解决了哪些问题
Redis 集群模式(Cluster)正是冲着上面这三个问题来的。
首先是水平扩展。集群把数据分散到多个主节点上,每个主节点负责一部分数据。当数据量增长时,往里加节点,然后重新分配数据槽位就行,不需要停服,也不需要业务方大改代码。其次是高可用。每个主节点可以挂一个或多个从节点,主节点挂了,从节点会自动晋升为新的主节点,业务无感,运维人员不用大半夜爬起来手工切换。再次是性能分摊。读写请求会分散到不同节点,虽然单节点依然是单线程执行命令,但整体吞吐量会随着节点数增加而同步上涨。
需要注意的是,Redis 集群并不是简单的"主从复制 + 哨兵"。哨兵模式解决的是主从自动切换的问题,但它本身不解决数据水平扩展的问题,所有数据仍然在同一套主从结构上。集群模式则是把数据切成很多片,每个片独立做主从复制和故障转移,哨兵那套机制在集群里被内置实现了。
1.3 集群模式背后的设计:哈希槽、主从与 Gossip
Redis 集群的数据分布,是通过"哈希槽"(hash slot)来实现的。整个集群固定划分成 16384 个槽位,每个 key 通过 CRC16 算法算出一个 16bit 的哈希值,再对 16384 取模,得到这个 key 属于哪个槽位。集群创建时,这些槽位会被均匀分配到各个主节点上。
一个 key 存到哪个节点,跟 key 本身的名字没有直接关系,跟 key 算出来的槽位有关系。所以你在集群模式下执行 SET foo bar,客户端会先算一下 foo 落在哪个槽位,然后连接负责那个槽位的节点去执行。key 分散在多个节点,这就是水平扩展的基础。
每个主节点下还可以挂从节点。从节点实时同步主节点的数据变更,一旦主节点被判定为不可用,从节点会发起选举,竞选成功后就升级为新的主节点。集群节点之间通过 Gossip 协议互相传递状态信息,端口上默认是服务端口加 10000,比如 Redis 服务端口是 6379,那集群内部通信的端口就是 16379。这个端口经常被防火墙忽略,后面排查问题时会专门讲到。
2. 部署前准备:版本选型、节点规划与环境调优
2.1 节点规划与资源评估
集群最小规模是 3 个主节点,因为至少要有 3 个主节点才能组成一个可用集群。为了保证高可用,每个主节点至少要配一个从节点,所以最常见的最小部署是 3 主 3 从共 6 个节点。
节点怎么规划,跟你手里的服务器数量直接相关。如果是 3 台物理机或者虚拟机,建议每台机器部署两个 Redis 实例,一个主一个从,但主从关系必须打散。比如机器 A 上放 master1 和 slave2,机器 B 上放 master2 和 slave3,机器 C 上放 master3 和 slave1。这样任何一台机器宕机,集群里最多丢失一个主节点,而它的从节点在其他机器上,可以正常完成故障转移。如果图省事,把某个主节点和它的从节点放在同一台机器上,那这台机器一挂,这个主节点和它的备份同时没了,集群就会直接失去这个主节点的服务,是要出大事的。
内存和 CPU 的资源评估,有一个简单的心算法:先估算业务需要缓存的总数据量,除以主节点数量,就得到每个主节点上预估的数据量。每个 Redis 实例的 maxmemory 至少要大于这个值,同时要小于服务器物理内存减去系统和其他进程占用后的剩余量。如果准备在一台服务器上跑两个 Redis 实例,那么两个实例的 maxmemory 加在一起,建议不要超过物理内存的 70%,留出给系统内核页缓存和 fork 临时内存的余量。
2.2 版本选型:Redis 5.x、6.x、7.x 该选哪个
版本选择上,我个人的建议是:新项目直接上 7.0.x 稳定版,老项目从 5.x 或 6.x 迁移的话,也优先考虑 7.0.x,因为很多优化点很有吸引力。
从集群功能的完整度来看,Redis 5.0 是一个分水岭。5.0 之前,创建集群要用外部的 redis-trib.rb 脚本,那个脚本依赖 Ruby 环境,部署时得多折腾一层。5.0 之后,集群创建和管理功能直接做进了 redis-cli,命令就是 redis-cli --cluster 子命令,简单了很多,这也是为什么现在大部分教程都基于 5.0 以上版本。
Redis 6.0 引入了多线程 IO、ACL 权限控制和 SSL 加密传输,对于安全要求高的生产环境非常有用。Redis 7.0 进一步改进了 AOF 持久化机制,引入了 Multi Part AOF,可以减小 AOF 重写时对内存和磁盘的压力,同时优化了内存碎片整理。如果你没有特别的兼容性限制,直接选 7.0 的最新小版本,比如 7.0.12 或更新版本,体验会好很多。
2.3 环境检查与系统参数调优
正式安装 Redis 之前,我习惯先调整几个 Linux 内核参数,虽然不调也能跑,但调完之后集群在极端场景下要稳不少。下面这几个是相对关键的。
# 内存分配策略,避免后台持久化 fork 时被系统杀掉 sysctl -w vm.overcommit_memory=1 # 关闭透明大页,防止 fork 时内存开销暴涨 echo never > /sys/kernel/mm/transparent_hugepage/enabled # 增大 TCP backlog,高并发连接场景下减少丢连接 sysctl -w net.core.somaxconn=1024vm.overcommit_memory 设置为 1,含义是内核总是允许内存超额分配,不要做严格检查。Redis 在做持久化时会 fork 子进程,如果系统内存分配策略太保守,可能在 fork 时直接被判定失败,导致主进程崩溃。关闭透明大页(THP)同样是为了减少 fork 时的内存开销。THP 开启时,内存页会变成 2MB 的大页,fork 时复制页表的开销会显著增大,在数据量大的实例上甚至会造成秒级卡顿。
另外还要检查一下防火墙。集群节点之间需要通信的端口有两段:一段是客户端连接的端口,比如 6379;另一段是集群内部通信的集群总线端口,也就是客户端端口加 10000,比如 16379。如果这两段端口没有放行,集群节点之间互相发现不了,建集群时就会一直卡在 Waiting for the cluster to join。
还有一个容易被忽略的是文件描述符限制。Redis 单实例在连接数多的时候,文件描述符消耗很快。建议把 ulimit -n 至少调到 65535。如果是通过 systemd 管理 Redis 服务,需要在 service 文件里加 LimitNOFILE=65535,光在 shell 里 ulimit 是不生效的。
3. Redis 集群一步一步搭起来
3.1 下载、编译与安装 Redis
我用源码编译的方式安装,这样版本可控制,编译参数也能按需调整。先下载 Redis 源码包,官方下载地址是 download.redis.io,如果服务器访问官方源慢,可以换国内镜像源。
cd /usr/local/src wget https://download.redis.io/releases/redis-7.0.12.tar.gz tar xzf redis-7.0.12.tar.gz cd redis-7.0.12 make -j4 make install PREFIX=/usr/local/redismake install 之后,二进制文件会装到 /usr/local/redis/bin 目录下,里面有 redis-server、redis-cli、redis-check-aof、redis-check-rdb 等工具。装完以后,把 /usr/local/redis/bin 加进 PATH,方便后续操作。
echo 'export PATH=/usr/local/redis/bin:$PATH' >> /etc/profile.d/redis.sh source /etc/profile.d/redis.sh3.2 节点配置文件的编写
我用的演示拓扑是 3 台服务器,每台服务器跑两个 Redis 实例,一个主一个从。三台机器的 IP 假定为 192.168.10.11、192.168.10.12、192.168.10.13,每台机器上的两个实例分别监听 6379 和 6380 端口,总共 6 个节点。
先创建目录结构。每台机器上执行:
mkdir -p /data/redis-cluster/6379 mkdir -p /data/redis-cluster/6380 mkdir -p /usr/local/redis/logs6379 实例的配置文件 /data/redis-cluster/6379/redis.conf 内容如下:
port 6379 bind 0.0.0.0 protected-mode no daemonize yes pidfile /var/run/redis_6379.pid logfile "/usr/local/redis/logs/redis_6379.log" dir /data/redis-cluster/6379 cluster-enabled yes cluster-config-file nodes-6379.conf cluster-node-timeout 15000 appendonly yes appendfilename "appendonly-6379.aof" maxmemory 2gb maxmemory-policy allkeys-lru配置里有几个关键点,我逐个说一下。
cluster-enabled yes 是开启集群模式,这是最核心的一项。cluster-config-file 指定集群状态文件,Redis 会把当前节点的集群信息写进这个文件,文件位置相对于 dir 配置的目录。cluster-node-timeout 是最重要的集群参数之一,表示节点被判定为不可达的超时时间,单位是毫秒。这里配置的 15000 表示 15 秒。超时时间设太短,网络稍微抖动一下就可能触发主从切换;设太长,主节点宕机后恢复时间也会变长,业务受影响的时间就久。个人经验是 15000 毫秒是个比较平衡的值。
maxmemory 配置的是这个实例可以使用的最大内存。如果配置了 2gb,超过之后就按 maxmemory-policy 设定的淘汰策略清理数据。这里用的是 allkeys-lru,也就是在所有 key 中按 LRU 算法淘汰最近最少使用的 key。如果你的集群是纯缓存场景,这个策略很合适;如果集群里存的是不能随便丢的业务数据,那 maxmemory 就要用心衡量,配合 noeviction 策略,宁可报错也不能默默淘汰数据。
如果集群需要开启密码认证,需要多加两个配置项:
requirepass Redis@123456 masterauth Redis@123456requirepass 是客户端访问当前节点时需要的密码,masterauth 是当前节点作为从节点时,连接主节点进行复制时使用的密码。这两个必须同时配置,否则故障转移时,新晋级的从节点没法通过认证去同步数据,主从复制会一直报错。
6380 实例的配置和 6379 基本一样,只需要把端口、pidfile、logfile、dir、cluster-config-file、appendfilename 里的 6379 全部替换成 6380。我通常会写一个简单的模板脚本批量生成,不容易漏项。
3.3 启动所有节点
节点配置完成后,逐个启动 Redis 实例:
/usr/local/redis/bin/redis-server /data/redis-cluster/6379/redis.conf /usr/local/redis/bin/redis-server /data/redis-cluster/6380/redis.conf三台机器都执行完以后,检查一下进程状态:
ps -ef | grep redis-server输出里应该能看到 6 个 redis-server 进程。此时集群还没创建,节点虽然启动了,但都还是孤立状态。用 redis-cli 连上去看集群信息,会看到 cluster_state:fail,这是正常的,因为槽位还没分配。
redis-cli -p 6379 cluster info3.4 用 redis-cli 创建集群
接下来是核心一步。在任意一台机器上执行 redis-cli --cluster create 命令,把所有节点一次性带进来。
/usr/local/redis/bin/redis-cli --cluster create \ 192.168.10.11:6379 192.168.10.11:6380 \ 192.168.10.12:6379 192.168.10.12:6380 \ 192.168.10.13:6379 192.168.10.13:6380 \ --cluster-replicas 1--cluster-replicas 1 的意思是每个主节点配 1 个从节点。redis-cli 会自动分配哪些节点当主,哪些节点当从,并给出一个槽位分配计划。执行后屏幕会输出主从分配方案和每个节点负责的槽位范围,然后问你 Can I set the above configuration?,输入 yes 确认。
如果集群设置了密码,创建命令也要带上 -a 参数:
/usr/local/redis/bin/redis-cli -a Redis@123456 --cluster create \ 192.168.10.11:6379 192.168.10.11:6380 \ 192.168.10.12:6379 192.168.10.12:6380 \ 192.168.10.13:6379 192.168.10.13:6380 \ --cluster-replicas 1创建完成后,redis-cli 会输出 [OK] All 16384 slots covered 的提示,看到这句话就表示集群已经可用了。
3.5 验证集群状态与数据读写
集群创建完成,先看整体状态。
redis-cli -p 6379 cluster info输出中 cluster_state 应该显示 ok,cluster_slots_assigned 显示 16384,cluster_known_nodes 显示 6。再看节点详情:
redis-cli -p 6379 cluster nodes输出会很长,每一个节点一行,格式大致是:
节点ID 地址 角色 状态 槽位角色字段里有 master 和 slave,连接状态一般是 connected。master 节点的行末尾会列出它负责的槽位范围,slave 节点行里能看到它跟随的主节点 ID。
验证数据读写时,记得加 -c 参数,也就是集群模式。如果不加 -c,redis-cli 不会自动帮你做节点跳转,SET 时如果 key 的槽位不在当前节点上,会直接报 MOVED 错误。
redis-cli -c -p 6379 127.0.0.1:6379> SET user:name "zhang"如果 user:name 这个 key 的槽位被分配到另一台机器上,你会看到类似这样的输出:
-> Redirected to slot [14390] located at 192.168.10.13:6380 OK这表示客户端已经被自动引导到了正确的节点去执行命令。再用 GET 取一下,也是同样效果。到这里,一个最简单的 3 主 3 从集群已经跑起来了。
4. 集群高可用实测:故障切换和扩容缩容全过程
4.1 模拟主节点宕机,观察自动故障转移
集群搭完,不能只看状态,还得真的把主节点搞挂一次,确认它在无人干预的情况下能自动恢复服务。
先看当前集群里哪个节点是主节点,以及它的从节点是谁。
redis-cli -p 6379 cluster nodes | grep master选定一个主节点,比如 192.168.10.12:6379,我们把它 kill 掉。
pid=$(redis-cli -h 192.168.10.12 -p 6379 info server | grep process_id | awk -F: '{print $2}') kill -9 $pidkill 之后,这个主节点对应的从节点会开始发起选举。cluster-node-timeout 配置的是 15000 毫秒,也就是说正常情况下大约 15 秒到 20 秒之间,从节点就会完成晋升。等待几十秒,然后重新查看集群节点状态:
sleep 20 redis-cli -p 6379 cluster nodes这时能看到 192.168.10.12:6379 原本的从节点变成了 master,而原来那个被杀掉的主节点变成了 fail 状态。
接下来把旧主节点拉起来。重新启动 Redis 服务:
/usr/local/redis/bin/redis-server /data/redis-cluster/6379/redis.conf启动后,旧主节点会以从节点的身份自动加入集群,并开始跟随新的主节点做复制。你会发现节点角色从 master 变成了 slave,状态恢复成 connected。整个过程没有人工干预,集群始终保持可用。
这里有一个关键经验:如果配置了 requirepass 但没有配置 masterauth,杀掉主节点后,从节点虽然能晋升为新的主节点,但旧主节点恢复后没法通过认证跟新主节点建立复制关系,会一直处于握手失败状态。所以密码场景下,masterauth 一定不能省。
4.2 集群扩容:加入新的主节点和从节点
业务量增长后需要扩容,Redis 集群支持在线添加节点。我先演示添加主节点。
假设新机器是 192.168.10.14,在上面安装 Redis,创建实例 6379(主)和 6380(从),配置方法跟前面一样。启动两个实例后,先把 6379 这个空节点加进集群。
redis-cli -p 6379 --cluster add-node 192.168.10.14:6379 192.168.10.11:6379命令格式是 add-node 新节点地址 集群中任意一个已存在节点的地址。执行成功后,新节点会以主节点身份加入集群,但此时它身上没有任何槽位,也就没有数据。可以用 cluster nodes 确认。
让新主节点真正承担数据,需要把一部分槽位从老节点迁移过来。这一步用 reshard 子命令:
redis-cli -p 6379 --cluster reshard 192.168.10.14:6379 \ --cluster-from c8d3e5f... \ --cluster-to 新主节点的ID \ --cluster-slots 4096--cluster-from 指定从哪个节点迁出槽位,可以写多个节点 ID,用逗号分隔;--cluster-to 指定接收槽位的节点 ID;--cluster-slots 指定要迁移多少个槽位。如果不确定节点 ID,先用 cluster nodes 查一下。
如果希望从所有老主节点均匀迁槽位,可以把 --cluster-from 写成 all。迁移过程中 Redis 集群会正常对外服务,只是对应槽位上的 key 会逐步搬过去,期间访问这些 key 会有额外的重定向开销,但不会中断。
添加从节点的方式:
redis-cli -p 6379 --cluster add-node 192.168.10.14:6380 192.168.10.11:6379 \ --cluster-slave --cluster-master-id 目标主节点ID加上 --cluster-slave 参数表示新节点作为从节点加入,--cluster-master-id 指定它要跟随的主节点 ID。执行完成后,新从节点会开始从主节点同步数据。
4.3 集群缩容:安全摘除节点
缩容比扩容多一步:主节点必须先清空槽位,再摘除;从节点可以直接摘除。直接删除一个身上还有槽位的主节点是不允许的,集群会报错。
先摘从节点:
redis-cli -p 6379 --cluster del-node 192.168.10.14:6380 从节点的ID然后摘主节点。先把主节点上的槽位移走,再执行删除。
redis-cli -p 6379 --cluster reshard 192.168.10.14:6379 \ --cluster-from 待删除主节点的ID \ --cluster-to 接收节点的ID \ --cluster-slots 4096槽位数量填的是这个主节点当前负责的槽位数。迁移完成后,用 cluster nodes 确认这个节点已经没有任何槽位,再执行:
redis-cli -p 6379 --cluster del-node 192.168.10.14:6379 待删除主节点的ID整个缩容过程中,被迁移的只是槽位上的数据,其他节点的服务不受影响。但迁移大量槽位时,会产生不小的网络和 CPU 开销,建议选在业务低峰期操作。
5. 高频故障与排查方法,踩坑实录
5.1 集群一直停在 Waiting for the cluster to join
执行 redis-cli --cluster create 后,长时间卡在 Waiting for the cluster to join,这是建集群时最常见的故障。原因大多是两种:一是集群总线端口(16379 等)被防火墙拦截,节点之间收不到 Gossip 消息;二是前面提到的 bind 配置有问题,节点之间无法通过 IP 互相访问。
排查思路很简单:先确认集群节点之间的基础网络连通性,用 telnet 或者 nc 检测端口。
telnet 192.168.10.12 16379如果端口不通,去防火墙里放行对应端口,同时检查云安全组是否也放行了。如果是 bind 0.0.0.0 配置没生效,节点日志里通常会有拒绝连接的记录,调整配置后重启实例再试。
5.2 集群状态变成 fail,报 CLUSTERDOWN
cluster_state:fail 意味着集群中有槽位没有节点在服务。常见原因有几个:主节点挂掉且它的从节点没有完成晋升,比如从节点也挂了,或者配置了 requirepass 但 masterauth 缺失导致复制失败;再比如超过一半的主节点同时不可达,集群会停止服务以保护数据一致性。
处理方式:先看 cluster nodes 输出,确认哪些节点处于 fail 或 disconnected 状态,把宕机的进程拉起来。如果某个主节点恢复后,集群状态仍然一直 fail,很可能是它无法跟自己的从节点建立复制关系。这时要检查日志里是否有 authentication 相关的报错,尽快补齐 masterauth 配置。
5.3 客户端一直报 MOVED 或 ASK 错误
在集群模式下,客户端拿到 key 之后,如果发现负责这个槽位的节点不是当前连接的节点,会返回 MOVED 错误并附上目标节点地址。这是集群协议的正常行为,但前提是客户端要能自动处理这种重定向。如果你用的是不支持集群协议的客户端,或者没有按集群模式创建客户端连接,就会出现明明服务端正常,客户端却一直报错的情况。
解决方法:一是把客户端换成支持 Redis Cluster 协议的版本,比如 JedisCluster、Lettuce 或者 go-redis 的集群客户端;二是临时排查时用 redis-cli -c 模式。生产环境不建议依赖普通客户端的自动重试去硬扛,应该在客户端侧就正确配置集群节点列表。
5.4 主从切换后数据同步报错
故障转移完成后,新晋升的主节点开始接收写入,旧主节点恢复后作为从节点去同步数据。如果配置了密码保护,并且没有设置 masterauth,就会看到类似 MASTER aborted replication with error: ERR Unauthorized 之类的日志。每台机器的每个节点都要配置 masterauth,而且密码必须和主节点的 requirepass 一致。
还有一种情况是旧主节点恢复后,它的数据集和新的主节点已经不一致。比如故障期间旧主节点还在运行,继续接收了写入(这种情况一般只在网络分区而非进程崩溃时出现),那么它重新加入集群时,会尝试进行一次全量同步来对齐数据。如果网络状况很差,全量同步反复失败,就要检查主从之间的网络延迟和 RDB 传输大小。
5.5 槽位迁移过程中出现访问超时
reshard 迁移期间,某些 key 被从源节点搬到目标节点,客户端在迁移窗口内访问这些 key 时,可能会收到 ASK 错误。支持集群协议的智能客户端会正确处理,但如果不支持的客户端,就会表现为访问超时或者报错。
所以生产环境做扩容或缩容前,要先确认客户端版本对集群重定向的支持情况,并且尽量控制单次迁移的槽位数量,不要一口气迁几千个槽位。我习惯每次迁 500 到 1000 个槽,观察集群负载和客户端报错情况,稳定后再继续。
6. 集群上线前的几个重要提醒
6.1 多 key 操作和 hash tag 的坑
集群模式和单机 Redis 最大的区别之一,就是多 key 操作的受限。单机上一条 MSET 可以一次写多个 key,或者在一个 Lua 脚本里多次读写不同 key;集群模式下,这些 key 如果不在同一个槽位,操作就会直接失败。
解决办法是强制业务 team 使用 hash tag。Redis 在计算哈希槽时,如果 key 里包含花括号,它会只对花括号内的内容做 CRC16 计算。比如 key 写成 user:1000:profile 和 user:1000:orders,在普通情况下可能落在不同槽位;但如果写成 {user:1000}:profile 和 {user:1000}:orders,两个 key 就会落在同一个槽位。凡是要一起操作的数据,设计 key 时就要提前规划好 hash tag,否则等业务上线后再改 key 格式,工作量会非常大。
6.2 上线前做一次故障切换演练
我强烈建议集群上线之前,挑一个业务低峰期做故障切换演练。不要等到线上出问题才验证。演练内容可以很简单:依次 kill 掉每个主节点,观察对应的从节点能否在预期时间内完成切换,业务读写是否正常。如果发现某个主节点切换后,它的从节点迟迟没有被提拔,大概率是集群配置有问题,趁早排查比线上踩雷强得多。
演练完之后,把 Redis 进程重新拉起,确认所有节点都恢复 connected 状态,复制关系正常,再宣布集群真正可用。这个流程走一遍,后面运维心里就有底了。
6.3 监控和日常运维的几个提醒
生产环境的集群,一定要有监控。至少要把 cluster_state 作为核心指标盯起来,一旦变成 fail 立刻告警。节点内存、命中率、主从复制延迟、慢查询日志都要纳入监控范围。常见的做法是用 redis_exporter 暴露 Metrics,配合 Prometheus 和 Grafana 展示,告警规则按集群角色分别设置。
还有一点,磁盘空间也要重点关注。集群模式下 AOF 和 RDB 文件会分散在各个节点上,如果某个节点磁盘写满,Redis 会拒绝写入,进而影响整个集群。给日志和持久化文件单独挂盘,并配置磁盘使用率告警,这个钱不能省。
我自己的习惯是每个季度对集群做一次巡检,内容包括:cluster info 状态、节点内存增长趋势、大 key 分布、主从复制延迟、持久化文件大小。发现问题早处理,比出事之后深夜上线改配置要舒服太多了。