Redis内存调配策略的那些事儿,实践中遇到的问题和解决思路分享
- 问答
- 2026-01-03 16:19:16
- 3
根据多位运维工程师和开发者在技术社区如CSDN、知乎、开源中国等的经验分享整理)
Redis内存调配策略的那些事儿,实践中遇到的问题和解决思路分享
说起用Redis,大家最开始关心的往往是它的速度有多快,能扛住多少并发,但用着用着,就会发现一个更现实、更常碰到的问题:内存不够用了,Redis是把数据都放在内存里的,服务器的内存再大也是有限的,所以怎么调配好这点宝贵的内存,就成了一个技术活,也是很多坑的来源。
首先得知道Redis是怎么“吃”内存的
Redis占用的内存,可不仅仅是咱们存进去的那个字符串或者对象本身那么大,它自己有个内部数据结构,比如存储一个简单的字符串键值对,除了键和值本身,Redis还会为这个键值对分配一些管理用的内存,比如记录键的类型、过期时间、指针等等,这些额外的开销,有时候比数据本身还大,特别是当你存了大量的小键值对,比如很多个只有几个字节的key和value,那么内存的浪费比例就会很高,这就好比用一个大箱子只装了一颗小糖果,箱子的重量可能比糖果还重。
(来源:Redis官方文档关于内存优化的章节)
第一个要有的意识就是:Redis的内存消耗 ≠ 你存入数据大小的简单相加,你得通过INFO memory命令去看看实际用了多少,分析一下内存都花在哪儿了。
核心策略:给内存上个“闹钟”和设定“淘汰规则”
内存有限,数据无限,这矛盾怎么解决?Redis提供了两个主要的武器:过期时间和内存淘汰策略。
过期时间(TTL): 这是预防性的,对于那些有时效性的数据,比如短信验证码、用户登录会话、临时缓存等,一定要在存入的时候就设置好过期时间,这样数据到期后会自动删除,相当于给内存做了自动清理,实践中很多内存爆掉的情况,就是因为忘了设置过期时间,或者设置的过期时间太长,导致大量不再需要的数据一直占着地方。
内存淘汰策略(maxmemory-policy): 这是补救性的,当Redis使用的内存达到你设定的上限(通过maxmemory配置)时,它就要开始“扔东西”了,扔哪些东西?这就是淘汰策略决定的,默认的策略通常是noeviction,意思是内存满了就不让写新数据了,会报错,这在很多场景下是不可接受的,因为会导致服务不可用。
我们一般会选用其他策略,
allkeys-lru:尝试淘汰最近最少使用的键,不管它有没有设置过期时间,这比较通用,能保证热数据留下来。volatile-lru:只从设置了过期时间的键中淘汰最近最少使用的,如果你能明确区分出核心数据和缓存数据,这个策略可以保护核心数据不被误删。allkeys-random:随机淘汰,这个很简单,但效果可能不稳定。volatile-ttl:淘汰即将过期的键,这个策略很聪明,反正它马上也要自己消失了,不如提前清掉。
(来源:Redis配置文件中关于maxmemory-policy的详细说明及社区讨论)
选择哪个策略,没有绝对答案,得看你的业务特点,比如你的数据访问模式有明显的热点,用LRU(最近最少使用)效果就好;如果你的数据过期时间很均匀,用TTL可能更高效。
实践中遇到的典型问题和解决思路
问题1:内存突然飙升,甚至被用满,导致服务宕机。
这是最吓人的问题,解决思路不是马上去扩容,而是先“破案”。
- 第一步:查监控。 看看是缓慢增长上来的,还是瞬间爆掉的,如果是瞬间,很可能是运行了某个大Key的操作或者批处理任务。
- 第二步:找“大块头”(大Key)。 使用
redis-cli --bigkeys命令(生产环境慎用,可能卡顿)或者用MEMORY USAGE key命令逐个怀疑对象检查,大Key的危害极大,一次读取或删除它都会严重阻塞Redis,导致其他请求超时,常见的大Key比如:一个Hash里存了几十万个字段,一个List里积压了上百万条消息。 - 解决思路: 找到大Key后,要拆分它,比如把一个大Hash按字段前缀拆成多个小Hash;对于积压的List,可以考虑用多个Key分片存储,或者从根本上优化业务逻辑,避免数据无限堆积。
问题2:设置了淘汰策略,但内存还是慢慢被撑满,淘汰策略好像没起作用。
这种情况也很常见。
- 原因分析: 很可能你的淘汰策略是
volatile-lru或volatile-ttl,但你发现内存里绝大部分的Key都没有设置过期时间!这样一来,淘汰策略能淘汰的对象非常少,自然就效果不彰了。 - 解决思路: 重新审视你的数据分类,哪些是必须持久化的核心数据(可以不设过期时间),哪些是纯粹的缓存(必须设过期时间),如果业务上很难区分,那就干脆改用
allkeys-lru策略,让Redis可以从所有Key里做淘汰,虽然可能误伤,但总比服务挂掉好,要检查代码,确保该设过期时间的缓存数据都正确设置了。
内存碎片率过高,明明显示有很多内存空闲,却报错说内存不足。
Redis删除一个Key后,释放的内存空间可能是一块不连续的小空间,如果后续申请的内存大小和这些碎片对不上,就无法利用,这就成了碎片。
- 查看方法:
INFO memory命令里的mem_fragmentation_ratio指标,如果这个值远大于1.5(比如超过2甚至3),就说明碎片很严重了。 - 解决思路:
- 重启Redis是最简单暴力的方法,但 downtime 时间太长。
- 从Redis 4.0开始,支持了内存碎片自动整理功能(通过配置
activedefrag yes开启),这个功能会在后台慢慢整理内存碎片,对性能有一定影响,但通常比服务不可用要好,实践中可以开启,并设置一个触发整理的碎片率阈值。
总结一下
Redis内存管理不像用魔法,配置好了就一劳永逸,它更像是一门需要持续观察和调整的艺术,关键是要做好监控,了解自己数据的特征(大小、冷热、生命周期),然后对症下药,结合使用合适的过期时间、淘汰策略,并警惕大Key和内存碎片这些“隐形杀手”,平时多看看INFO命令的输出,就能对Redis的健康状况心中有数了。

本文由酒紫萱于2026-01-03发表在笙亿网络策划,如有疑问,请联系我们。
本文链接:https://www.haoid.cn/wenda/73799.html
