redis maxmemory应设为总内存的60%–70%(如16gb机器设12gb),并预留15%–20%余量应对碎片、aof重写及系统开销,避免oom。

maxmemory 设置多少才算“合理”
没有固定值,取决于你的物理内存、业务峰值写入量、以及是否与其他进程共用机器。常见错误是直接设成 maxmemory 2gb 而不预留系统缓冲——Redis 实际占用会略高于这个值(比如碎片、AOF 缓冲、客户端连接内存),导致 OOM killer 杀掉进程。
建议留出 15%~20% 内存余量:如果服务器总内存 16GB,Redis 最大设到 12gb 比较稳妥;若 Redis 是唯一服务且内存充足,也别设满,14gb 是更安全的上限。
实操建议:
- 先用
INFO memory查看当前used_memory_rss和mem_fragmentation_ratio,确认真实内存压力 - 在压测环境模拟高峰流量,观察
used_memory_peak上升趋势,取其 1.2 倍作为初始maxmemory - 避免使用百分比单位(如
maxmemory 80%),Redis 不支持该语法,只认字节或带单位的数值(512mb、2gb)
allkeys-lru 的实际行为和陷阱
allkeys-lru 看似“全局淘汰最近最少用的 key”,但 Redis 并非真遍历全部 key 做精确 LRU,而是采样淘汰:每次触发回收时,从 key 空间随机采样 maxmemory-samples 个(默认为 5),从中挑出最久未访问的淘汰。这意味着它是个近似 LRU,不是严格时间序。
容易踩的坑:
Redis 缓存和数据结构管理技能。通过自然语言操作 Redis,支持 String、Hash、List、Set、ZSet、Stream 等数据结构操作。当用户提到 Redis、缓存、消息队列、会话存储时使用此技能。
- 采样数太小(比如保持默认 5),在 key 数量极大(千万级)且访问模式高度倾斜时,可能漏掉真正冷的数据,导致缓存命中率意外下降
- 如果你混用了长期存储型 key(如配置项、白名单)和临时缓存 key,
allkeys-lru会一视同仁地淘汰它们——哪怕你给配置项没设过期时间,它也可能被干掉 - 某些客户端 SDK(如早期 Jedis)在 pipeline 中批量写入时,可能让 Redis 误判访问时间戳,造成“刚写入就淘汰”的假象
如何验证回收是否按预期工作
不能只看 INFO stats 里的 evicted_keys 是否增长,那只能说明“有淘汰发生”,无法判断淘汰逻辑是否符合业务预期。
关键检查点:
- 连上 Redis 后执行
CONFIG GET maxmemory-policy,确认返回确实是allkeys-lru,不是拼错成allkey-lru或漏了- - 用
MEMORY USAGE <key></key>抽查几个典型 key,对比它们的idletime(单位:秒),再结合INFO memory中的evicted_keys和keyspace_hits/keyspace_misses推断淘汰倾向 - 在测试环境用脚本持续写入带不同访问间隔的 key(例如每 1s、10s、60s 访问一次),然后填满内存,观察哪些 key 先消失——这比读文档更直观
为什么不能只靠 maxmemory + allkeys-lru 就高枕无忧
这套组合能防止 OOM,但解决不了根本问题:如果业务持续写入冷数据(比如日志类、一次性 token),allkeys-lru 会不断把“刚热起来”的缓存挤出去,导致缓存雪崩式失效。
真正需要配合的是应用层策略:
- 对明确不该进缓存的数据(如错误请求参数、爬虫路径),在接入层就拦截,别让它触达 Redis
- 对必须缓存但生命周期固定的 key(如用户权限快照),主动加
EX或PX,改用volatile-lru更可控 - 定期用
SCAN+OBJECT IDLETIME扫描长 idle 的 key,人工归档或清理,避免全靠自动回收兜底
内存警戒线不是调完就完事的静态参数,它得和业务写入节奏、key 生命周期、监控告警联动——否则 evicted_keys 突增时,你看到的只是结果,不是原因。










