背景
2022年7月27日晚,21:05分 新功能上线后,通过Grafana上查到Redis多个性能指标有很大的升高,Redis使用的是腾讯云的云服务
这里通过这个问题,记录和总结整个排查过程,Redis相关指标变化如下
1.cpu和内存参数
cpu利用率: 9%->99%(100%)
内存使用率: 波动维持在正常范围(约1%)
2.网络监控参数
连接数量: 波动维持在正常范围(约2%)
连接使用率: 波动维持在正常范围(约1%)
入流量: 0.54Mbps->27Mbps
入流量使用率:0.2%->13.2%
出流量: 3Mbps->5Mbps
出流量使用率:0.9%->1.84%
3.请求监控
读请求命中率:100W->3100W
问题定位
通过实例名称,在腾讯云Redis看到后台当前机器在2022/07/27 21:00-22:00,也就是新功能上线的时间段,性能指标如上图所示
其中 在【延时分析】这一块看到多个Redis指令的请求数有明显升高,其中在该时间段【eval】指令占总数的90%,初步判断是该命令导致Redis各项性能指标抖动
这里查询到【eval】是Redis执行脚本的命令参数,排查后发现项目中的Redis客户端Redisson大量利用该命令去执行Redis脚本,最终将拆解到各个服务后,发现主要是两处
【1】Redisson分布式锁,加锁和释放锁,以及看门狗对当前持有锁的线程续期时,会使用到eval 命令执行脚本
【2】Redisson延迟队列,将任务加入到延迟队列后,Redisson会使用eval命令指定脚本 定时查询任务是否到期
针对第1点
Redisson分布式锁,加锁,释放锁,判断可重入锁,看门狗锁续期的过程中会使用到eval命令,其中较为频繁的操作是在当前持有锁的线程进行看门狗续期,排查后没有发现该长期占有锁的线程的业 务场景
针对第2点
Redisson延迟队列,底层通过netty 的 HashedWheelTimer 时间轮实现通过eval脚本不断查询到是否有达延迟时间的任务和到期时间,考虑到这个点,迅速排查了项目中新功能关联的业务,主要是在以下场景有使用到 Redisson延迟队列, 1.黑名单 2.用户注销 3.订单下单,其中前两个场景,对比功能上线前后,数据量和QPS无波动,但是第三个场景,下单量暴增50倍,进一步排查订单业务,发现在实现订单自动过期时,使用了Redisson延迟队列
为了进一步确认,复现线上环境的场景,将订单业务在测试环境上复现,通过脚本在20S内创建了2000个订单,然后在redis 客户端 使用monitor命令监控,发现eval命令不在订单过期时间内不断增加,5分钟达到了上百万次,基本可以确认是订单暴涨导致Redisson延迟队列不断轮轮询查询订单的过期时间导致客户端短时间发送多个eval指令造成服务端redis参数指标抖动
解决方案
针对上文的问题定位结果,暂时选择了使用RocketMQ作为延迟队列,来替代Redisson作为延迟队列,在测试环境发布后,使用monitor确认eval命令有明显降低
查询相关文档后发现,暂时Redisson延迟队列不适合在业务密集的场景使用,除了会导致短时间内Redis性能抖动,对于数据量大且延迟敏感的场景,误差会比较大
参考
下一篇文档对Redisson延迟队列的实现做进一步分析
https://www.likecs.com/show-305347100.html
https://wenku.baidu.com/view/7f4c0d54f142336c1eb91a37f111f18583d00cda.html
https://jishuin.proginn.com/p/763bfbd71961
https://blog.csdn.net/Wu_Shang001/article/details/120609138