
我做了八年 Redis 运维和架构踩过的坑比很多教程里写的最佳实践要多得多。今天不聊面试八股纯讲生产环境里那些真正要命的问题从部署方式怎么选、缓存穿透怎么防、主从哨兵集群到底怎么搭才不出岔子到分布式锁的正确写法、Lua 脚本的应用边界最后把最常见的故障排查思路一次性捋清楚。这篇实战笔记适合刚接手 Redis 生产环境的后端开发、运维和架构师也适合那些 IDE 里能跑通、一上生产就掉链子的同学参考。1. 部署选型与基础运维别在最简单的环节翻车1.1 部署方式的取舍裸机、Docker 还是 Windows很多人第一次装 Redis 都是在本机 Windows 环境下载个压缩包解压、双击 redis-server.exe 就跑起来了。但在生产环境这么干会出大问题Windows 版本 Redis 官方并不推荐用于生产它更像是给本地开发调试用的。我在实际运维中见过某团队把 Redis 部署在 Windows Server 上QPS 一高 CPU 直接飙到 90%排查半天才发现是 Windows 版 Redis 的异步 I/O 模型在底层实现上和 Linux 版有差异性能损耗很明显。生产环境的主流方案是 Linux 裸机部署或者容器化部署。裸机部署的好处是可控性强内存、CPU、磁盘、网络都是独占的出问题排查链路短性能上限也高。缺点是扩缩容要手动处理机器故障需要人工介入。Docker 部署的好处是环境一致性极好从开发到测试到生产的镜像是一致的而且用 docker-compose 或者 K8s 编排主从、哨兵集群时特别方便副本扩容只需要复制一份配置再改几个参数。坏处是容器自身的网络隔离和资源限制如果没配好会出现一些诡异的问题比如容器内存限制没设置极端情况下 OOM 杀进程后又自动重启日志里却看不到明显的 error。如果单纯从生产可靠性角度我个人的习惯是中小规模应用、流量可控且团队没有专职运维的用 Docker 部署核心链路、大流量、对延迟和稳定性有极端要求的直接物理机或云主机部署。Windows 环境只用于本地开发和功能验证千万别让它进生产。1.2 部署后的基础检查和配置文件里的保命参数装完 Redis 之后干的第一件事不是急着写业务代码而是改配置。默认配置下 Redis 是裸奔的尤其是以下这几个参数不改就是留隐患。# redis.conf 关键配置 bind 0.0.0.0 # 生产环境建议绑定内网 IP不要用 0.0.0.0 requirepass password # 一定设置访问密码 protected-mode yes # 保护模式保持开启 rename-command CONFIG # 建议禁用或重命名 CONFIG 命令 maxmemory 实际可用内存的70% # 必须设置内存上限 maxmemory-policy allkeys-lru # 淘汰策略要提前想好 appendonly yes # AOF 持久化开关 appendfsync everysec # AOF 刷盘策略maxmemory这个参数要单独拎出来说。很多人以为 Redis 是缓存内存满了就删老的没问题。但你如果不设置maxmemoryRedis 默认是 64 位系统下不限制内存使用它会一直把数据写到内存耗尽然后触发操作系统 OOM Killer。这个时候 Redis 进程被杀了还好问题是它可能把同机的其他进程一起带走这就是典型的缓存雪崩之外的人为雪崩。内存淘汰策略的选择要看业务场景。allkeys-lru适合大多数缓存类业务用 LRU 算法淘汰最近最少使用的 key。volatile-ttl适合只对设置了过期时间的 key 做淘汰、永不过期的 key 不允许淘汰的场景。noeviction适合队列类、强一致性的业务场景内存满了直接返回 OOM 错误把淘汰谁的决策权交还给业务方。这个决定要提前做因为线上数据量上来之后切换淘汰策略会导致大量 key 被淘汰缓存命中率剧烈抖动。1.3 可视化客户端怎么选从 Redis Desktop Manager 到开源替代热词里反复出现redis desktop manager和another redis desktop manager说明很多人一直在用这两个工具。RDM 旧版确实是免费开源的但新版已经转向商业授权模式社区里开源旧版仍然有不少人在用。这里我建议留意一下授权合规的问题团队商业化项目里如果不想有授权隐患优先考虑开源替代。我在生产环境管理多个 Redis 实例主从、哨兵、集群时会用Another Redis Desktop Manager它的节点管理做得不错支持 Cluster 模式的拓扑展示查看 key 时可以按 TTL 排序、按类型过滤还支持直接编辑 Hash 里的 field对日常巡检和问题定位来说效率很高。另一个值得提的是RedisInsight这是 Redis 官方推出的可视化工具功能最全支持内嵌终端、内存分析、命令辅助。不过资源占用偏高低配开发机上会有明显卡顿。可视化工具只是辅助定位问题的真正生产故障排查还得靠命令行redis-cli的--latency、--bigkeys、MONITOR这些才是杀手锏后面故障排查部分会详细展开。2. 数据类型与缓存治理把 Redis 用到点子上2.1 五大数据类型的核心使用边界Redis 的数据类型面试题人人都能背但到了实际生产中发现用错数据类型的例子比比皆是。String 是最基础的适合存会话、计数、缓存对象序列化字符串。有个容易忽略的坑String 类型的SET key value NX EX是分布式锁的基础但很多人会用SETNX加锁后再EXPIRE两步操作不具备原子性进程在两步之间挂掉锁就永远不释放了。所以务必用一条SET key value NX EX seconds完成加锁。Hash 类型适合存对象属性比如用户信息、商品详情好处是支持对单个 field 做增减操作不需要把整个对象读出来反序列化再塞回去。这里要提醒一下如果 Hash 里的 field 特别多要注意内存碎片和哈希表扩容带来的阻塞风险一个 Hash 超过 5000 个 field 时建议考虑拆分成多个 key。List 类型适合消息队列、时间线列表LPUSH配合BRPOP就能实现一个简单的阻塞队列。但生产环境对消息可靠性有要求时别用它当正式 MQRedis List 队列没有确认机制消费者处理到一半挂了消息就丢了这个场景建议换专业的消息队列。Set 类型适合做标签、去重、共同关注这类集合运算SINTERSTORE计算共同好友的效率很高。ZSet 类型是排行榜场景的主力ZADD维护热度榜单ZRANGEBYSCORE做范围查询但要注意当分值相同的元素比较多时ZREVRANGE的分页会出现数据重复或漏数据这时需要辅助唯一标识作为 score 的小数位来保序。2.2 缓存治理穿透、击穿、雪崩的生产级处理缓存穿透、击穿、雪崩这个问题是我在面试考察候选人和生产事故复盘里都会反复提的。穿透是指查询一个不存在的数据缓存里没有、数据库里也没有导致每一次请求都打到数据库。治理方案第一选择是布隆过滤器把所有可能存在的数据的 key 提前 Bloom Filter 里查询时先过滤如果布隆过滤器判断不存在就直接返回空不再打到数据库。需要注意的是布隆过滤器存在误判率用guava的 BloomFilter 时要根据数据量设置合理的fpp误判率不然误判过高会导致大量无效查询穿透到数据库。第二选择是空值缓存把不存在的 key 也缓存一个空值设置一个较短的过期时间比如 60 秒这样短时间内的重复请求不会打到 DB。但空值缓存有个隐患如果后面数据真的被写入了缓存里还是空值需要考虑主动删除该缓存或用较短的过期时间来自动纠正。击穿是指一个热点 key 在缓存过期的瞬间大量请求同时打到数据库。处理方案是用分布式锁或本地锁来保证只有一个请求去 DB 重建缓存其他请求等待锁释放后再从缓存读取。更成熟的做法是逻辑过期缓存不设置物理过期时间而是 value 里存一个逻辑过期时间后台异步线程发现逻辑过期后去刷新缓存。这样可以在缓存过期瞬间直接返回旧数据异步完成更新完全避免击穿。缺点是实现复杂度高且旧数据返回会有一段时间的不一致。雪崩的情况更复杂通常是因为大量 key 设置了相同的过期时间、或 Redis 实例宕机导致缓存层整体不可用请求全部打到 DB 造成 DB 过载。预防方案有三层一是给缓存过期时间设置随机抖动基础过期时间加一个随机分钟数避免同一时刻大面积过期二是 Redis 本身的高可用架构必须到位主从加哨兵或者 Cluster保证单点宕机不会导致缓存层整体消失三是做多级缓存兜底比如热点数据在 Redis 前面再加一层本地缓存Caffeine即使 Redis 整体不可用本地缓存还能扛住一部分核心流量给 DB 争取喘息时间。值得强调的是这三类问题的治理不是选一个方案就完事穿透和雪崩可能会同时发生。比如 Redis 集群宕机雪崩时请求全部穿透到 DBDB 压力骤增后响应变慢慢请求堆积又导致大量请求超时重试最终压垮整个服务链路。所以生产上我会要求同时部署空值缓存、热点 key 逻辑过期、多级缓存兜底三层防线。2.3 序列化方案选型为什么你存进去的对象取出来变成了乱码热词里有redis序列化这也是我经常被问到的一个点。问题通常表现为用可视化工具打开 Redis 一看key 前面多了一串\xAC\xED\x00\x05t\x00之类的二进制前缀value 也看不懂。这是 JDK 序列化的杰作。Spring Boot 默认的 RedisTemplate 如果没配置序列化器会用 JdkSerializationRedisSerializer它会把对象序列化成 Java 特有的二进制格式还带类信息。跨语言的团队如果别的服务用 Python 或者 Go 来读就会很痛苦可读性差还容易踩序列化漏洞。生产环境的正确做法是统一使用 JSON 序列化比如 Jackson 或 Fastjson如果还在用的话注意 Fastjson 的历史漏洞。配置时要注意几个细节第一是GenericJackson2JsonRedisSerializer相比Jackson2JsonRedisSerializer会保存class信息反序列化时能自动识别类型但会额外增加存储空间第二是 LocalDateTime 这类 Java 8 时间类型默认 JSON 序列化会出问题需要注册 JavaTimeModule第三是最容易被忽视的你要保证类结构不能随意增删字段否则老的缓存数据反序列化会失败。我见过某团队上线新版本时给实体类加了一个必填字段结果所有老缓存数据反序列化直接抛异常缓存层直接批量退役流量全部打到 DB险些酿成事故。序列化选型的建议如果你的 Redis 消费方只有 Java 服务且追求省空间可以用 protobuf如果有多语言消费需求推荐 JSON 并做好 class 兼容性控制。另外无论用哪种序列化方案上线前都要压测验证对象大小一个不注意把 500KB 的大对象塞到 Redis 里内存增长和数据网络传输延迟都会被放大。3. 高可用架构主从、哨兵与集群的实战递进3.1 主从复制三分钟搭完但要懂它的弱点和延迟主从复制是 Redis 高可用最基本的一环。配置方式不复杂从节点配置文件里加一行replicaof master-ip master-port或者直接命令行SLAVEOF。用 Docker 部署主从时我推荐用 docker-compose 直接编排稍微注意一下网络模式要用同一个 overlay 网络或者 host 模式保证主从之间端口互相能通。# docker-compose 编排主从示例 services: redis-master: image: redis:7.0 command: [redis-server, --appendonly, yes, --requirepass, 123456] ports: - 6379:6379 redis-slave: image: redis:7.0 command: [redis-server, --replicaof, redis-master, 6379, --masterauth, 123456, --requirepass, 123456] depends_on: - redis-master ports: - 6380:6379主从复制有个关键参数很容易踩坑repl-backlog-size。它决定从节点断线重连时增量同步的能力。默认值是 1MB生产环境建议调到 64MB 或更高。如果从节点断线太久超过 backlog 缓冲范围就会触发全量同步full resync这个过程会把主节点的 RDB 快照传输给从节点。在主节点数据量大、带宽不足时全量同步会导致主节点阻塞RDB 生成期间 CPU 和 IO 都会飙高这段时间主节点的响应延迟会明显增加。另外要记住主从复制默认是异步的主节点确认写入成功不代表从节点已经同步完成。如果主节点宕机且未同步的数据已经过了min-replicas-to-write的设置就会发生数据丢失。所以生产环境要配置min-replicas-to-write 1 min-replicas-max-lag 10这个配置的意思是如果从节点数量少于 1 个或从节点同步延迟超过 10 秒主节点就拒绝写入。这是牺牲可用性换取数据一致性的典型设置生产核心链路建议开启非核心链路可以关掉。3.2 哨兵集群从主从切换到自动故障转移的细节主从复制解决不了主节点宕机后写入不可用的问题哨兵Sentinel的出现是为了实现自动故障转移。哨兵本身是一个独立运行的 Redis 进程它通过 PING/PONG 监控主从节点的健康状态当检测到主节点客观下线且通过投票达成一致后会选举一个从节点提升为新的主节点并把其他从节点的复制目标自动切换过去。用 Docker 部署哨兵集群时docker-compose的编排里要特别注意 master 节点的服务名解析。因为 Sentinel 之间是通过 IP 进行仲裁的容器重启后 IP 会变化导致 quorum 仲裁失败。解决方法是给容器设置固定 IP或者配置SENTINEL resolve-hostnames yes。另一个实际运维中非常容易忽视的点是Sentinel 配置文件里sentinel monitor mymaster master-ip master-port quorum必须指向主节点的真实 IP而 Docker 容器起来之前 IP 是未知的所以需要先启动 master 容器、拿到 IP再在哨兵配置里填入。这个先后顺序问题导致很多第一次用 Docker 部署哨兵的人卡壳。哨兵模式里最核心的参数是quorum和failover-timeout。quorum 表示多少个哨兵同意主节点下线才执行故障转移建议设置为哨兵总数的半数加一比如 3 个哨兵就设 2。failover-timeout控制故障转移的超时时间默认 180 秒太长了生产环境建议调短到 30~60 秒否则主节点故障后写入中断时间会很长。实际故障转移演练中我踩过一个典型的坑业务连接的是哨兵节点但使用的是普通的RedisTemplate直连一旦主节点发生切换业务连接的主节点地址还是旧的导致大量连接报错。正确的客户端连接方式是连接哨兵集群由客户端自己感知主节点变化。3.3 Cluster 集群当单机或主从扛不住流量和容量时当数据量达到几十 GBQPS 达到几十万时主从加哨兵的架构会遇到两个问题单机内存不够存所有数据单节点 CPU 接近瓶颈。这个时候需要 Cluster 集群把数据分片到多个主节点上。Cluster 模式把键空间分成 16384 个哈希槽hash slot每个主节点负责一部分槽位。写入时CRC16(key) 16383计算 key 属于哪个槽客户端会直接访问对应槽所在的主节点。这带来一个限制多 key 操作MGET、管道如果 key 不在同一个节点上就无法直接执行需要使用 hash tag 强制把相关 key 放到同一个槽。hash tag 的用法是 key 里用花括号包住相同内容比如user123:{order}和user456:{order}会被路由到同一个槽位这样就可以做管道批量操作了。搭建 Cluster 集群时最少要求是 3 个主节点生产环境为了高可用还会给每个主节点配上从节点。手动搭建的过程比较繁琐需要先启动所有节点再用redis-cli --cluster create来完成槽位分配。实操时我用的是 Docker 容器加固定 IP 的方式配置文件和端口提前规划好# 每个节点一个容器目录端口从 7001 到 7006 docker run -d --name redis-7001 --net host \ -v /data/redis/7001/redis.conf:/etc/redis/redis.conf \ redis:7.0 redis-server /etc/redis/redis.conf # 创建集群3 主 3 从 redis-cli --cluster create \ 192.168.1.101:7001 192.168.1.102:7002 192.168.1.103:7003 \ 192.168.1.104:7004 192.168.1.105:7005 192.168.1.106:7006 \ --cluster-replicas 1Cluster 模式下客户端连接要特别注意不能连接单个节点然后依赖转发默认集群模式关闭了重定向生产环境必须使用支持 Cluster 的客户端让它自己去感知槽位变化。运维层面监控 Cluster 的指标里最需要关注的是cluster_state这个值如果变成fail意味着有节点失联导致的槽位覆盖不完整业务读写会直接报错。我建议用监控工具Zabbix 或 Prometheus redis_exporter对cluster_state做实时告警这个指标异常代表的是整个集群级别的故障。4. 分布式锁与 Lua 脚本高并发正确性的最后一道防线4.1 分布式锁的演进从 SETNX 到 RedLock 再到红锁争议分布式锁是 Redis 在分布式场景里最经典的能力之一。我面试时最喜欢考察一个问题用 Redis 实现分布式锁时你的锁在极端情况下还成立吗很多候选人能答出 SETNX 加锁、EXPIRE 设置过期时间但问业务执行时间超过锁过期时间怎么办就懵了。最简单可用的分布式锁实现是加锁时用一条原子命令完成加锁和设置过期时间SET lock:order:1001 owner_id NX PX 30000解锁时不能简单地DEL。因为如果 A 线程的锁因为超时已经被释放B 线程重新获取了锁A 线程执行完业务后如果直接 DEL就会把 B 的锁误删。正确做法是 LUA 脚本先比较 value 是否是自己设置的用唯一 token 标识相等才删这个比较加删除必须原子进行if redis.call(get, KEYS[1]) ARGV[1] then return redis.call(del, KEYS[1]) else return 0 end这个方案已经能解决绝大多数场景的问题但它还是存在两个隐患。第一是业务执行时间超过锁过期时间锁自动释放了但业务还没跑完其他线程就能拿到锁造成并发冲突。解决方案是用 Redisson 提供的看门狗watch dog自动续期机制。Redisson 在获取锁后会默认启动一个后台线程每隔锁过期时间的三分之一默认 10 秒过期每 3 秒续一次自动续期业务执行完手动解锁时才会终止这个后台线程。这是市面上唯一一个把续期逻辑内置成熟的方案我非常推荐直接使用 Redisson 而不是自己造轮子。第二个更隐蔽的坑是主从切换时的锁丢失。在 master 节点上加锁成功后如果 master 宕机、从节点还没有同步这个锁记录就被提升为新 master新 master 上就没有这个锁记录其他线程就能成功加锁。针对这个问题Redis 官方提出 RedLock 算法要求在多个独立部署的 Redis 节点上同时加锁超过半数的节点加锁成功才认为加锁成功。但 RedLock 在分布式系统领域有比较大的争议很多专家认为它依赖了时钟同步等不现实的假设建议谨慎使用。我的实践结论是在单实例或主从架构内使用 Redisson 的普通锁配合看门狗已经能覆盖绝大多数分布式锁场景如果对锁的可靠性有极端要求比如防超卖、防重复扣款建议引入 ZooKeeper 等强一致性协调服务不要为了强行使用 Redis 去调复杂性极高的 RedLock。4.2 Lua 脚本在生产中的应用和边界Lua 脚本是 Redis 里非常实用但经常被忽略的能力。Lua 可以实现多个命令的原子执行中间不会被其他命令插入。典型场景包括限流器的原子滑动窗口用 ZSET 记录请求时间戳用 Lua 一次完成清除过期记录的判断、计数、设置过期时间三个步骤库存扣减先判断库存是否充足充足再扣减否则返回错误整个过程原子完成。下面是一个我经常用的滑动窗口限流 Lua 脚本-- KEYS[1]: 限流 key -- ARGV[1]: 窗口大小毫秒 -- ARGV[2]: 窗口内最大请求数 local current redis.call(PTTL, KEYS[1]) if current 0 then -- key 不存在重新生成窗口 redis.call(INCR, KEYS[1]) redis.call(PEXPIRE, KEYS[1], ARGV[1]) return 1 end local count redis.call(GET, KEYS[1]) if count and tonumber(count) tonumber(ARGV[2]) then return 0 end redis.call(INCR, KEYS[1]) return 1注意上面脚本里 PTTL 的用法key 不存在时 PTTL 返回 -2key 存在但没有设置过期时间时返回 -1我把两种情况合并用 0判断能覆盖 key 刚初始化时的场景。脚本返回 1 表示放行0 表示拒绝。Lua 脚本在生产中有一个致命性能陷阱如果脚本在单个 Redis 节点上执行时间过长内部包含大量循环Redis 是单线程模型所有其他命令都会阻塞在脚本执行期间。我在压测中发现一个含 5 万次循环的 Lua 脚本会让 Redis 的响应延迟从毫秒级飙升到秒级。所以 Lua 脚本里绝对不能写大循环复杂的遍历逻辑尽量拆到业务侧处理或者用 KEYS 预先把所需数据一次性传入。另外每次调用脚本前Redis 需要先对脚本做 SHA 校验和缓存如果脚本内容频繁变化会导致 script cache 抖动最好用固定的SCRIPT LOAD预加载脚本业务侧只传 SHA 值。5. 生产故障排查与运维实录把踩过的坑都记下来5.1 典型故障清单从内存到命令的八大高频问题第一类是内存问题最常见的是used_memory持续升高但数据量并没有明显增长。先跑redis-cli --bigkeys看大 key再注意内存碎片率mem_fragmentation_ratio。如果碎片率超过 1.5说明内存碎片严重可以在低峰期执行debug jemalloc或者直接重启节点让 jemalloc 整理内存。第二类是延迟抖动用redis-cli --latency -h ip -p port监控实时延迟如果延迟周期性飙升检查是否开启了 RDB 快照save参数或 AOF 重写这两个操作都会 fork 子进程导致父进程短暂阻塞。生产环境建议把save关闭只保留 AOF 持久化。第三类是连接数告警Redis 默认maxclients是 10000如果频繁报max number of clients reached优先检查客户端连接池是否配置合理以及是否存在连接泄漏程序获取连接后未归还。第四类是热点 key 集中问题典型现象是某一个 key 的访问量占整个 Redis 访问量的 60% 以上。用redis-cli --hotkeys需要开启maxmemory-policy的 LFU可以扫描出热点 key治理方案是把热点 key 打散成多个副本比如在 key 后加随机后缀分散访问压力或者加一层本地缓存提前消化掉一部分流量。第五类是慢查询日志通过SLOWLOG GET 20查看执行超过阈值的命令常见的有KEYS *、SMEMBERS在超大 set 上执行、以及大 value 的GET。这里我再次强调生产环境千万不要用KEYS做模糊匹配它的复杂度是 O(n)会直接卡死 Redis 单线程。用SCAN代替。第六类是 AOF 文件无限增长问题定位方法很简单检查是否配置了auto-aof-rewrite-percentage 100和auto-aof-rewrite-min-size 64mb。触发自动重写时 Redis 会 fork 子进程整理 AOF 文件如果数据量大且磁盘 IO 能力弱这个 fork 过程对主进程会产生秒级阻塞。第七类是内存淘汰策略设置不当表现为缓存命中率低但内存曲线平滑。用redis-cli --stat持续观察keyspace_hits和keyspace_misses如果命中率长期低于 80%排查是不是淘汰策略过激比如allkeys-lru在业务里把热点 key 也淘汰了建议切换成allkeys-lfu或细化 key 的过期时间。第八类是主从延迟异常INFO replication里看master_repl_offset和从节点的slave_repl_offset差值差值持续增大说明复制流跟不上写入量检查是否有大量大 value 写入或者 backlog 过小导致的频繁全量重同步。5.2 排查思路接到告警后我一般按什么顺序操作告警响了之后不要慌按照固定路径排查能省很多时间。第一步看内存和 CPU连接 Redis 后执行INFO memory和INFO stats重点看used_memory、instantaneous_ops_per_sec、total_commands_processed先确定是资源瓶颈还是命令瓶颈。第二步看慢日志SLOWLOG GET 5确认有没有耗时的慢命令。慢日志的阈值可以用CONFIG SET slowlog-log-slower-than 10000临时调低单位微秒10000 就是 10 毫秒方便在问题期间捕获更多慢命令。第三步看客户端连接情况CLIENT LIST查看连接来自哪些 IP、每个连接空闲多久。有一次排查连接数暴涨我发现有几十个连接来自同一个 IP且clients状态全是idle判断是某个服务的连接池配置了永不过期导致连接堆积。第四步看主从状态INFO replication确认主从链路是否正常是否有节点处于断线状态。第五步如果需要看实时访问模式可以用MONITOR命令短暂开启注意别开太久MONITOR本身会降低 Redis 性能观察 30 秒到 1 分钟确认是不是有某类 key 异常高频读写。这套顺序的核心逻辑是先确认资源层有没有瓶颈再确认命令层有没有问题最后才看业务访问模式。我见很多团队一上来就MONITOR然后被大量输出刷屏反而抓不住重点效率极低。5.3 日志与监控构建最小闭环的可观测性生产环境 Redis 绝对不能裸奔不监控。我的最低要求是采集以下指标内存使用率used_memory和maxmemory的直接占比、连接数当前连接和maxclients的占比、命中率keyspace_hits和keyspace_misses、慢日志数量、主从偏移量差、cluster_state集群模式必须。采集方式用 Prometheus 加 redis_exporter 是最通用的组合Grafana 里可以配置行一屏展示所有 Redis 节点的关键指标。告警阈值我参考的实践值是指标告警阈值说明内存使用率连续 2 分钟超过 80%预留空间防止 OOM 和淘汰风暴连接数超过maxclients的 80%排查连接泄漏命中率低于 80% 持续 5 分钟检查缓存策略或热点访问变化主从延迟偏移量超过 100MB检查大 value 和复制积压情况Redis 进程存活离线 1 分钟触发故障转移预案日志层面Redis 默认只在启动和重大错误时打日志所以核心排查依赖redis-cli的实时命令输出而不是日志文件。如果你用 Docker 部署记得把容器的 stdout 日志收集到统一的日志平台ELK 或 Loki这样在容器重启、异常退出时能保留当时的运行记录。个人运维经验里还有一个必做项所有核心 Redis 节点都配置好maxmemory和appendonly yes后同时确认持久化文件RDB/AOF有自动备份机制至少要做到崩溃后从 AOF 文件能恢复到最近一秒的数据。这也是为什么我强烈建议生产环境开启 AOF 而不是只依赖 RDB 快照。6. 常见问题速查与避坑技巧6.1 问题定位速查表现象可能原因排查命令/操作连接拒绝protected-mode 开启且未配置密码或 bind检查配置文件和requirepass延迟偶发飙升RDB 快照或 AOF 重写导致短时阻塞INFO persistence看rdb_bgsave_in_progress内存持续增长内存碎片或未设置maxmemoryINFO memory看mem_fragmentation_ratio缓存全部失效大量 key 设置了同时过期检查过期时间分布增加随机抖动主从数据不一致主从不定期全量重同步调大repl-backlog-size检查网络带宽集群写入报错节点失联导致槽位覆盖不完整CLUSTER INFO看cluster_state锁总是失效业务超时但锁未续期改用 Redisson 或手动续期大 key 拖垮命令单个 key 存储了超大集合redis-cli --bigkeys定位并拆分6.2 几条少有人提的避坑技巧第一无论用 Docker 还是裸机都建议把 Redis 的appendfsync设为everysec。如果设为always性能会下降明显如果设为no最坏情况下会丢一秒以上的数据。折中下来everysec是最平衡的选择。第二不要在容器里以 root 用户运行 Redis最好用单独的 redis 用户并限制容器只读根文件系统这能防止 Redis 被入侵后影响宿主机。第三使用集群模式时客户端的初始化不要用单个节点的地址死连要做多节点地址 failover 配置否则集群节点重启或槽位重新分配时会出现大范围连接断层。第四对FLUSHALL、FLUSHDB之类的命令在生产环境建议做重命名或禁用处理。我见过一次线上事故就是因为同事在测试环境执行残留窗口的FLUSHALL结果把连到同一 Redis 的生产库数据全部清空。启用rename-command FLUSHALL 可以避免这类高危误操作。第五如果你的 Redis 被用于存储验证码、Token 等临时数据务必设置合理的过期时间同时配合 LRU 淘汰作为兜底避免程序异常导致 key 堆积把内存涨爆。6.3 从一次真实事故看缓存治理的全局思考最后分享一次我经历过比较有代表性的事故某个电商大促活动中商品详情接口的缓存 key 过期时间统一设置为 30 分钟大促开始后的第 30 分钟瞬间出现大量缓存穿透数据库连接数打满接口超时率飙升。复盘下来有两个教训一是统一过期时间必然导致雪崩应该把过期时间打散二是活动期间的热点 key爆款商品的详情根本无法通过普通的缓存过期机制来保护必须对这些 key 做兜底。后续我们针对商品详情做了逻辑过期加异步刷新同时引入本地缓存 Caffeine 做二级缓存大促期间缓存命中率稳定在 97% 以上没有再出过问题。这个案例的核心经验是Redis 的缓存治理不能只依赖 Redis 本身需要和业务侧一起设计。热点识别、过期时间策略、多级缓存兜底这些都要在系统设计阶段就规划好等到线上出问题再补就晚了。从我个人的实践体会来看Redis 用得好的团队一定不是会写命令的团队而是懂数据边界、懂故障模式、懂容量规划的团队。希望这篇实战笔记能帮你把这些问题考虑得更周全。
拿不准这条消息跟你有没有关系?
工种不同、批次不同,要求可能差很多。打电话把你的情况说清楚,我们按信阳、平顶山本地的口径给你捋一遍。