先验证“特定时段变慢”是否真实:用redis-cli --latency连续测5分钟并对比基线;若Max latency整点突增(如0.3ms→12ms)才确认,否则优先排查业务定时逻辑或连接池。

确认是否真在特定时段变慢
别急着查 Redis 内部,先验证“特定时段变慢”是不是真实现象。很多情况下,延迟升高其实是客户端侧或网络侧的周期性波动,比如定时任务触发大量请求、监控采集脚本集中拉取、或上游服务在整点批量刷缓存。
用 redis-cli --latency -h <host> -p <port></port></host> 在疑似时段前后连续测 5 分钟,再对比基线(低峰期同样时长)。如果 Max latency 稳定在 0.3ms,而整点突增至 12ms,那才算确认——否则优先排查业务侧定时逻辑或连接池复用策略。
检查慢日志和命令分布是否时段集中
Redis 的 SLOWLOG 是最直接的线索来源,但它默认只记录执行时间 > 10ms 的命令(由 slowlog-log-slower-than 配置)。如果变慢是整点发生,大概率对应某类命令在该时段高频出现。
- 执行
SLOWLOG GET 20,重点看时间戳是否集中在整点前后 ±30 秒内 - 用
redis-cli info commandstats查各命令调用量,对比高峰/低峰的cmdstat_set:calls、cmdstat_del:calls、cmdstat_hgetall:calls是否翻倍 - 特别注意
KEYS *、SCAN未带COUNT、LRANGE biglist 0 -1这类命令——它们可能被定时脚本调用,但没做分页或限流
盯住内存淘汰与过期键清理的节奏
如果设置了 maxmemory,且淘汰策略是 allkeys-lru 或 volatile-lru,那么当写入量在特定时段激增(如每小时 flush 一批缓存),Redis 就会在内存触顶后密集执行淘汰逻辑。这个过程不是匀速的,而是“攒一批、清一波”,导致周期性延迟毛刺。
关键指标要看 redis-cli info stats | grep -E "(evicted_keys|expired_keys|instantaneous_ops_per_sec)":
-
evicted_keys在整点是否跳涨?说明内存压力集中释放 -
expired_keys是否同步飙升?说明大量 key 刚好设了相同 TTL(比如统一设为 3600 秒),到期时间对齐 - 如果
instantaneous_ops_per_sec并不高,但延迟却高,基本可锁定是淘汰/过期清理阻塞主线程
此时 lazyfree-lazy-eviction yes 和 lazyfree-lazy-expire yes 就不是可选项,而是必开项——它把内存释放挪到后台线程,避免卡主进程。
排查外部干扰:fork、swap、大页
周期性性能下滑还常来自操作系统层。RDB 快照默认每 60 秒检查一次是否需要保存(由 save 规则触发),若规则设为 save 3600 1,那每小时整点就会 fork 一次子进程。fork 在大内存实例上可能耗时几十毫秒,期间主线程完全停顿。
验证方式:
- 查
redis-cli info persistence | grep rdb_bgsave_in_progress,看是否在变慢时段为 1 - 用
cat /proc/<redis-pid>/status | grep VmRSS</redis-pid>看 RSS 内存大小,若 > 10GB,fork 开销不可忽视 - 检查
/sys/kernel/mm/transparent_hugepage/enabled是否为[always]—— 是的话,必须关掉,否则 fork + 内存分配都会变慢 - 运行
free -h和swapon --show,确认没启用 swap;哪怕只用了 1% swap,延迟也会从微秒级跳到毫秒级
真正难缠的,是那些看似无关的“定时动作”:备份脚本调用 redis-cli bgsave、运维巡检跑 redis-cli --bigkeys、甚至系统 cron 每小时执行 updatedb 导致 I/O 抢占。这些不会出现在 Redis 日志里,得去 ps auxf 和 atop 里找。



















