一次大Key过期导致线上Redis延迟的案例分析

Posted by WGrape的博客 on April 12, 2021

文章内容更新请以 WGrape GitHub博客 : 一次大Key过期导致线上Redis延迟的案例分析 为准

前言

本文原创,著作权归WGrape所有,未经授权,严禁转载

一、现象

在9日凌晨0点后 ,bigkey为 api_axxxxxxx 的HASH数据过期,导致Redis出现无法连接的情况,大概8分钟后,服务器内存逐渐恢复正常,Redis服务也恢复正常,如下图所示

img

image

二、问题

在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分的时候就完成了整个内存的释放

image

对于从服务器(内存充足)来说,完成删除52G内的操作,只用了1分钟时间,和上述推测中Redis删除52G内存所需要的时间一致。所以可以确定,正常情况下,此删除操作只需要1分钟,而不至于需要8分钟

(3) 排除内存回收异常

影响内存回收的因素一般是碎片,但通过主服务器的监控可以发现,在操作前后内存碎片都没有明显变化,所以也可以排除内存回收的因素

image

如果在释放大量内存后,内存碎片如果没有明显变化,则说明“内存”是虚拟内存,即数据并非完全在物理内存中,而是把部分数据存储在了Swap空间中

2、确定影响因素

目前可以凭上述推断,确定是由于Swap原因导致,下面需要做的就是尽量还原当时的场景,找到证据。

3、还原主服务器场景

(1) 删除前内存占用

在主服务器删除数据之前,操作系统126G的内存,仅Redis数据就已经高达93G,可剩内存仅剩10%左右。所以可以进一步推测当时Redis所需要的内存,物理内存不能提供或操作系统优先选择了使用Swap空间

image

image

(2) 使用了Swap空间

查看内存详细情况,发现在当前内存占用77G比93G小的情况下,都有使用9G的Swap空间,所以到当时场景应该也发生了Swap

image

通过查看主服务器在凌晨时段内的监控发现,仅在9日凌晨的0至8分钟内,有明显的硬盘读取操作,和Redis服务瘫痪的时间完全吻合。

image

image

所以可以确定在这段近7分钟的时间内发生了Swap,导致Redis需要等待Swap完全结束后,才能正常执行,这就是导致额外7分钟耗时的原因。另外由于Swap会把硬盘中的数据重排到内存,所以这也是为什么释放大量内存后,碎片几乎没有变化的原因

4、确定结论

近8分钟左右的卡顿,Redis自身耗时约1分钟左右,剩下约7分钟的额外耗时,由发生的Swap导致