文章内容更新请以 WGrape GitHub博客 : 一次大Key过期导致线上Redis延迟的案例分析 为准
前言
本文原创,著作权归WGrape所有,未经授权,严禁转载
一、现象
在9日凌晨0点后 ,bigkey为 api_axxxxxxx
的HASH数据过期,导致Redis出现无法连接的情况,大概8分钟后,服务器内存逐渐恢复正常,Redis服务也恢复正常,如下图所示
二、问题
在bigkey过期的时候,为什么导致Redis服务出现了近8分钟的卡顿 ?
三、推测
1、删除操作在主线程触发
如果 bigkey 过期的删除操作,在后台线程触发,即使需要很长时间,但至少不会引起Redis服务的卡顿
2、Redis自身耗时
从测试推论可知,对于52G的数据删除,Redis自身需要52秒的消耗,即在没有出现任何意外情况下,Redis需要约1分钟的时间删除这个数据
3、发生了额外的意外耗时
由于Redis自身消耗只需要1分钟的时间,那么说明剩下的7分钟时间一定用在了意外的耗时上
四、排查
1、基本影响因素
从耗时因素分析可知,影响Redis删除操作耗时的原因,主要有网络堵塞、时间复杂度高、内存回收异常、Swap延迟四个因素。
(1) 排除网络
由于此删除操作由过期机制自动触发,所以和网络没有关系,排除网络堵塞的情况
(2) 排除时间复杂度
通过观察 10.10.xx.xx
从服务器在8日晚至9日凌晨近20分钟内的监控,发现对于从服务器来说,在凌晨8分的时候,从服务器接收到 “删除内存” 的指令后,在9分的时候就完成了整个内存的释放
对于从服务器(内存充足)来说,完成删除52G内的操作,只用了1分钟时间,和上述推测中Redis删除52G内存所需要的时间一致。所以可以确定,正常情况下,此删除操作只需要1分钟,而不至于需要8分钟
(3) 排除内存回收异常
影响内存回收的因素一般是碎片,但通过主服务器的监控可以发现,在操作前后内存碎片都没有明显变化,所以也可以排除内存回收的因素
如果在释放大量内存后,内存碎片如果没有明显变化,则说明“内存”是虚拟内存,即数据并非完全在物理内存中,而是把部分数据存储在了Swap空间中
2、确定影响因素
目前可以凭上述推断,确定是由于Swap原因导致,下面需要做的就是尽量还原当时的场景,找到证据。
3、还原主服务器场景
(1) 删除前内存占用
在主服务器删除数据之前,操作系统126G的内存,仅Redis数据就已经高达93G,可剩内存仅剩10%左右。所以可以进一步推测当时Redis所需要的内存,物理内存不能提供或操作系统优先选择了使用Swap空间
(2) 使用了Swap空间
查看内存详细情况,发现在当前内存占用77G比93G小的情况下,都有使用9G的Swap空间,所以到当时场景应该也发生了Swap
通过查看主服务器在凌晨时段内的监控发现,仅在9日凌晨的0至8分钟内,有明显的硬盘读取操作,和Redis服务瘫痪的时间完全吻合。
所以可以确定在这段近7分钟的时间内发生了Swap,导致Redis需要等待Swap完全结束后,才能正常执行,这就是导致额外7分钟耗时的原因。另外由于Swap会把硬盘中的数据重排到内存,所以这也是为什么释放大量内存后,碎片几乎没有变化的原因
4、确定结论
近8分钟左右的卡顿,Redis自身耗时约1分钟左右,剩下约7分钟的额外耗时,由发生的Swap导致