Redis内存突然飙升,感觉内存瞬间被撑爆了,真是吓人啊
- 问答
- 2025-12-30 11:25:07
- 2
(听到一位运维工程师在茶水间吐槽)哎哟我去,今天真是惊心动魄啊!下午三点多,监控平台突然哐哐报警,我一看,好家伙,一台核心业务的Redis服务器内存使用率像坐火箭一样,几分钟内从60%直接干到95%以上,眼瞅着就要撑爆了!我当时心里“咯噔”一下,冷汗都出来了,这要是服务崩了,整个APP的核心功能都得瘫痪,那可就出大事了!
我一边赶紧在群里喊人,一边手忙脚乱地连上服务器,第一反应是不是有哪个“熊孩子”程序员写了段死循环,在疯狂地往Redis里塞数据?(来自一次事故复盘会上某位工程师的调侃)但查了查慢查询日志,又好像没有特别异常的指令,这时候,有个细心的同事提醒了一句:“看看是不是key过期出了问题?”
这一下点醒了我,我赶紧用info命令仔细看了看内存相关的统计信息,果然发现了猫腻!used_memory高得吓人,但used_memory_dataset(实际数据占用的内存)的比例却没想象中那么高,再往下翻,看到了一个平时不太留意的指标——mem_fragmentation_ratio(内存碎片率),这个值已经超过了2.0!(根据Redis官方文档说明,该比值大于1表示有碎片,过高则说明碎片很严重)我心里大概有数了,很可能是内存碎片突然加剧,导致实际可用的空闲内存锐减,虽然数据量没怎么变,但操作系统看到的内存使用却爆了。
为了验证这个想法,我立刻用redis-cli --bigkeys命令扫了一遍,想看看有没有什么异常大的key突然出现,结果扫了一圈,并没有发现什么“巨无霸”key,那看来不是单个key惹的祸,这时候,另一个同事提到了一个可能性:“会不会是某个定时任务,一下子删除了海量的小key?” 因为Redis的过期键删除策略,尤其是惰性删除和定期删除结合的方式,在某些情况下,如果瞬间有大量key在同一时刻过期并被清理,确实可能会在短时间内产生大量的内存碎片。(这个观点在一些技术博客的Redis内存优化文章中常有提及)
眼看内存使用率还在98%的高位徘徊,服务已经开始出现轻微的延迟了,不能再等了,虽然知道在业务高峰期执行这个命令有点风险,可能会引起短暂的停顿,但也顾不了那么多了,我深吸一口气,在命令行里敲下了 memory purge 命令,强制Redis尝试清理内存碎片,敲下回车的那几秒钟,感觉特别漫长,眼睛死死盯着监控图表。
谢天谢地!几秒后,图表上的内存使用率曲线开始扭头向下,从98%一路缓慢下降,最终稳定在了70%左右,整个办公室的人都跟着松了一口气,真是吓死宝宝了!
事后我们仔细复盘,根源还真让我们猜对了,确实有一个不怎么起眼的缓存预热脚本,为了图省事,在设置一批临时活动数据时,给几十万个key统一设置了相同的、很短的有效期(比如5分钟),结果就是,这批key在几乎同一时刻失效,当Redis的后台线程进行清理后,留下了大量不连续的内存空间,新的写入请求进来,即使数据体量不大,也因为找不到足够大的连续空间来存放,导致Redis不得不向操作系统申请更多的内存,即便这些碎片空间的总和其实是够用的,这就好比一个停车场,虽然空车位总数还有很多,但都被零散地夹在已停车辆中间,这时候来一辆稍大点的车,就怎么也停不进去了,只能去开辟新的停车场。(这个比喻是当时我们团队内部讨论时,一个同事用来向产品经理解释的,非常形象)
这次虚惊一场,真是结结实实给我们上了一课,Redis这个老伙计,平时稳如老狗,但要是使用不当,冷不丁就会给你来个“内存惊魂”,以后再设置过期时间,可得长点心眼,尽量打散,避免集中失效了,还有啊,内存碎片的监控,也必须得加到日常巡检清单里去了,不能再这么被动挨打了。

本文由黎家于2025-12-30发表在笙亿网络策划,如有疑问,请联系我们。
本文链接:https://www.haoid.cn/wenda/71236.html
