3. Redis 内存配置:maxmemory 参数、内存淘汰触发时机、内存监控命令
在微服务架构中,Redis 作为缓存层,其内存管理直接决定了服务的稳定性与缓存命中率。本章深入剖析 Redis 内存配置的核心参数 maxmemory、淘汰机制的触发时机,以及生产环境必备的内存监控命令,帮助你在资源受限的场景下做出精准决策。
3.1 maxmemory 参数:内存上限的设定策略
maxmemory 是 Redis 实例允许使用的最大内存阈值,单位通常为字节。当 Redis 存储的数据量达到该阈值时,将根据配置的淘汰策略(eviction policy)自动移除旧数据,以容纳新写入。
3.1.1 配置方式
- 配置文件(redis.conf):
maxmemory 4gb - 运行时动态修改:
CONFIG SET maxmemory 4gb - 不设限制:
maxmemory 0(默认值,64 位系统下依赖物理内存)
⚠️ 生产环境警告:切勿将
maxmemory 设为 0。无限制的内存使用会导致 Redis 进程被 OOM Killer 强制终止,造成缓存雪崩与全链路故障。建议预留 20%-30% 的系统内存给操作系统和持久化子进程(如 RDB 快照、AOF 重写)。
3.1.2 设定建议
| 部署场景 | 推荐 maxmemory 比例 | 说明 |
|---|---|---|
| 纯缓存(无持久化) | 物理内存的 70% | 留足给 OS 页缓存和突发流量 |
| 缓存 + RDB 快照 | 物理内存的 60% | RDB 期间 fork 子进程使用 COW,内存可能翻倍 |
| 缓存 + AOF 重写 | 物理内存的 50% | AOF 重写同样依赖 COW,需更大缓冲 |
| 容器化部署(K8s) | 容器内存 limit 的 75% | 避免容器 OOM,同时给 JVM/Nginx 等 sidecar 留空间 |
3.2 内存淘汰触发时机:从阈值到动作
Redis 并非在内存达到 maxmemory 的瞬间立即淘汰数据,而是遵循一套精确的触发流程。理解这一时机,有助于你设计合理的缓存过期与淘汰策略。
3.2.1 触发条件
- 客户端发起写入命令:如
SET、LPUSH、SADD、ZADD等所有可能导致内存增长的操作。 - 当前内存 >= maxmemory:Redis 在每次写入前检查
used_memory是否超过阈值。 - 触发淘汰循环:Redis 调用
freeMemoryIfNeeded()函数,根据配置的策略逐出键,直到内存降至maxmemory以下。
💡 关键细节:只读命令(如
GET、EXISTS)不会触发淘汰。即使内存已超限,只要没有新写入,Redis 仍可正常服务读请求。这为监控告警争取了缓冲时间。
3.2.2 淘汰策略与触发频率
| 淘汰策略 | 触发后行为 | 性能影响 |
|---|---|---|
| noeviction | 直接返回 OOM 错误,不淘汰任何键 | 无额外 CPU 开销,但写入会失败 |
| allkeys-lru / volatile-lru | 采样 N 个键(默认 5),淘汰最近最少使用的 | 低,采样复杂度 O(1) |
| allkeys-lfu / volatile-lfu | 基于访问频率(近似计数器)淘汰 | 中,维护频率计数器有额外内存 |
| allkeys-random / volatile-random | 随机淘汰一个键 | 极低,无采样开销 |
| volatile-ttl | 淘汰剩余 TTL 最短的键 | 中,需要比较 TTL 值 |
3.3 内存监控命令:实时掌握内存水位
没有监控就没有优化。Redis 提供了一系列命令用于查看内存使用情况、键分布和淘汰统计,是微服务缓存调优的“仪表盘”。
3.3.1 核心监控命令
| 命令 | 输出关键字段 | 用途 |
|---|---|---|
INFO memory |
used_memory, used_memory_rss, maxmemory, mem_fragmentation_ratio | 整体内存水位与碎片率 |
MEMORY STATS |
peak.allocated, fragmentation.bytes, dataset.bytes | 更细粒度的内存分配统计 |
MEMORY USAGE <key> |
返回指定 key 的近似内存占用(字节) | 定位大 key(bigkey) |
MEMORY PURGE |
尝试回收空闲内存页(仅限 jemalloc) | 手动降低 RSS,缓解内存碎片 |
INFO stats |
evicted_keys, expired_keys, keyspace_hits, keyspace_misses | 淘汰次数与命中率统计 |
3.3.2 实战监控脚本示例
# 检查当前内存使用率与淘汰情况
redis-cli INFO memory | grep -E "used_memory:|maxmemory:|mem_fragmentation_ratio:"
redis-cli INFO stats | grep "evicted_keys"
# 找出内存占用最大的 5 个 key(需配合 --bigkeys 扫描)
redis-cli --bigkeys
# 实时查看内存变化(每秒刷新)
watch -n 1 "redis-cli INFO memory | grep 'used_memory_human'"
📌 微服务集成建议:在 Spring Boot 应用中,可通过 Actuator 的
/actuator/health 端点暴露 Redis 内存指标,或使用 Micrometer 的 RedisCacheMetrics 采集 evicted_keys 和 keyspace_hits,接入 Prometheus + Grafana 实现可视化告警。
3.4 内存淘汰触发与监控流程(SVG)
下图展示了从客户端写入请求到内存淘汰完成,再到监控反馈的完整链路,帮助你建立全局视角。
3.5 内存碎片与监控实战
内存碎片是 Redis 长期运行后的常见问题,直接影响可用内存和淘汰触发频率。通过 mem_fragmentation_ratio 可以快速诊断。
| 碎片率范围 | 状态 | 建议操作 |
|---|---|---|
| 1.0 ~ 1.5 | 健康 | 无需处理 |
| 1.5 ~ 2.0 | 轻度碎片 | 监控趋势,考虑重启或 MEMORY PURGE |
| > 2.0 | 严重碎片 | 计划维护窗口重启实例,或切换至 jemalloc 5.x |
🔧 生产案例:某电商 Redis 集群在双十一期间
evicted_keys 从 0 飙升至 2000/s,排查发现 mem_fragmentation_ratio 高达 3.8,实际数据仅占 2GB,但 RSS 占用 7.6GB。通过 MEMORY PURGE 回收后,RSS 降至 3.2GB,淘汰立即停止。后续在低峰期重启实例,碎片率恢复至 1.2。
3.6 本章小结
- maxmemory 是 Redis 内存管理的“安全阀”,必须根据持久化方式和部署环境合理设定,预留缓冲空间。
- 淘汰触发时机 仅在写入命令执行前检查,只读请求不受影响;理解这一点有助于设计读写分离架构。
- 监控命令 是微服务缓存调优的眼睛:
INFO memory看水位,INFO stats看淘汰,MEMORY USAGE找大 key。 - 内存碎片是隐藏的“内存黑洞”,定期检查
mem_fragmentation_ratio并配合MEMORY PURGE或重启策略,可有效降低淘汰频率,提升缓存命中率。