点击链接阅读原文,获取更多技术内容:一次访问Redis延时高问题排查与总结-阿里云开发者社区
作者抽丝剥茧的记录了一次访问Redis延时高问题的排查和总结。
作者 | 寒亭
来源 | 阿里云开发者公众号
20230308 在某地域进行了线上压测, 发现接口RT频繁超时, 性能下降严重, P50 400ms+, P90 1200ms+, P99 2000ms+。
细致排查发现其中重要的原因是, 访问缓存rt竟然飙到了1.2s左右。
作为高性能爱好者, 榨干CPU的每一分价值是我们的宗旨, 是可忍孰不可忍, 怎么能光空转, 不干活呢? 那就仔细分析下问题。
我们简化下Redis访问流程如下:
如下, 请求远远没有达到机器带宽, 不是瓶颈. 另外单独看了网卡重传率等指标, 也都正常。
那么很大概率就是客户端自身问题了. 我们把客户端详细放大如下:
根据当时ARMS监控结果如下, 虽然YGC次数与耗时有所上升, 但没有发生FGC:
把内存Dump出来, 分析JedisConnectionFactory几个相关重要指标, 发现问题有如下2个:
顺便说一句: maxBorrowWaitTimeMills, createdCount, destroyedCount 几个metrics信息是JedisPool对象持久维护的全局变量信息, 只要JVM不重启, 这个信息就会一直存在。这也就是为啥不需要在压测峰值时获取内存dump, 而是事后dump也可以。
此外, 如果细致探索JedisPool参数工作机制, 就需要了解apache的ObjectPool2的机制。刚好笔者在之前研究过ObjectPool, 后续会出单独文章阐述&对比ObjectPool, ObjectPool2, JedisPool以及经常踩坑的DruidPool的实现原理与差异。
本文就不再赘述, 敬请期待~
至此, 定位问题是JedisPool行为异常导致。
部分参数是由
redis.clients.jedis.JedisPoolConfig 继承而来
spring.redis.jedis.pool.max-active=100spring.redis.jedis.pool.max-idle=16spring.redis.jedis.pool.time-between-eviction-runs-millis=30000spring.redis.jedis.pool.min-idle=0spring.redis.jedis.pool.test-while-idle=truespring.redis.jedis.pool.num-tests-per-eviction-run=-1spring.redis.jedis.pool.min-evictable-idle-time-millis=60000
我们把问题简化为如下序列, 即可发现问题所在. 在T2~T3内, 84个对象创建, 84个对象销毁. 造成了极大的损耗。
由于线上环境, Redis服务器配置较高, 为了能充分压榨性能, 同时应对容器场景下典型的突发峰值, 因此如下行为:
内容剩余60%,完整内容可点击下方链接查看:一次访问Redis延时高问题排查与总结-阿里云开发者社区
阿里云开发者社区,千万开发者的选择。百万精品技术内容、千节免费系统课程、丰富的体验场景、活跃的社群活动、行业专家分享交流,尽在:阿里云开发者社区-云计算社区-阿里云