Redis设了maxmemory为什么还是内存溢出:这笔账不止键数据
给 Redis 设了 maxmemory,想着内存到顶就自动淘汰,结果机器还是报警 OOM——这是 Redis 运维里最常见的认知错位之一。根因一句话:maxmemory 统计的只是键数据,进程实际占的内存比这大,而多出来的部分不受淘汰策略管。把这笔账拆开,问题就清楚了。
第一层:maxmemory 算什么、不算什么
maxmemory 的口径是"数据占用":所有键值对及其底层结构。但 Redis 进程的内存账本里还有几项不在这个口径内:一是内存碎片——频繁的写入删除让分配器留下的空洞,碎片率高时能占到数据量的三到五成;二是复制缓冲区——主从架构下主节点为每个从节点维护的输出缓冲,从节点网络慢或全量同步时可能涨得很大;三是客户端缓冲区——每个连上来的客户端都有输入输出缓冲,慢客户端(比如一口气拉百万级数据不读的)能把缓冲撑大;四是 Lua 与订阅等运行开销。所以"maxmemory=8G、机器 16G 还是 OOM"完全可能:碎片 3G + 复制缓冲 2G + 客户端缓冲 1G,账就爆了。
第二层:默认策略本身是个坑
maxmemory 到顶后的行为由 maxmemory-policy 决定,而默认值是 noeviction——不淘汰,写就报错。很多 OOM 场景其实是没改这个默认值:写入被拒,应用报错;或者应用把报错吞了,看起来"没事"但数据一直写不进去。缓存场景应显式设置 allkeys-lru 或按 TTL 的 volatile-lru 等;有持久化和主从时还要理解 volatile 系策略在"没有 TTL 的键"上等于不淘汰的边界。
排查与治理清单
按顺序核四项:info memory 看 used_memory 与 used_memory_rss 的差值——差值大即碎片问题,4.0 以上版本可开 activedefrag 主动碎片整理,或安排低峰重启回收;info clients 与 client list 找输出缓冲异常的慢客户端,限其 buffer 与超时;info replication 看主从缓冲,从节点限速或错峰全量同步;最后核对 maxmemory-policy 是否显式设置、与应用场景匹配。容量规划口径同步修正:给 Redis 分内存时按"maxmemory + 预计碎片与缓冲余量"算,通常留三到五成余量,别让数据顶到物理内存。
总结成一句:maxmemory 是数据的水位线,不是进程的内存上限——碎片、复制缓冲、客户端缓冲三笔账在水位线之外,默认的 noeviction 还得主动改成匹配业务的策略。四项排查跑一遍,“设了上限还 OOM"基本都能定位到具体出处。
这类内存账的梳理属于日常巡检的功课,贵州诚鑫致达科技为企业做服务器与应用巡检时,缓存组件的健康核点是标准清单项,有类似问题欢迎留言交流。
(约 950 字)
企业存储选型参考|贵州诚鑫致达
做分支办公与入门升级,群晖机型参考:DS725+ · DS423+ · DS220+。需要选型建议或上门评估,搜「诚鑫致达」即可找到我们。