阿里云开发者社区,千万开发者的选择
阿里云开发者社区,百万精品技术内容、千节免费系统课程、丰富的体验场景、活跃的社群活动、行业专家分享交流,欢迎点击【阅读原文】加入我们。
阿里妹导读
作者抽丝剥茧的记录了一次访问Redis延时高问题的排查和总结。
背景
为啥Redis访问延时如此高?
可能性1: 服务端问题?
可能性2: 物理网络问题?
可能性3: 客户端问题?
顺便说一句: maxBorrowWaitTimeMills, createdCount, destroyedCount 几个metrics信息是JedisPool对象持久维护的全局变量信息, 只要JVM不重启, 这个信息就会一直存在。这也就是为啥不需要在压测峰值时获取内存dump, 而是事后dump也可以。
此外, 如果细致探索JedisPool参数工作机制, 就需要了解apache的ObjectPool2的机制。刚好笔者在之前研究过ObjectPool, 后续会出单独文章阐述&对比ObjectPool, ObjectPool2, JedisPool以及经常踩坑的DruidPool的实现原理与差异。
本文就不再赘述, 敬请期待~
至此, 定位问题是JedisPool行为异常导致。
如何解决问题?
线上JedisPool实际参数
部分参数是由 redis.clients.jedis.JedisPoolConfig 继承而来
spring.redis.jedis.pool.max-active=100
spring.redis.jedis.pool.max-idle=16
spring.redis.jedis.pool.time-between-eviction-runs-millis=30000
spring.redis.jedis.pool.min-idle=0
spring.redis.jedis.pool.test-while-idle=true
spring.redis.jedis.pool.num-tests-per-eviction-run=-1
spring.redis.jedis.pool.min-evictable-idle-time-millis=60000
参数行为解析
脉冲式请求引发的问题
期望的行为模式
spring.redis.jedis.pool.max-active=500 // 线上稳定保有4台, 4*500=2000, 仍然远小于Redis规格支持的3w
spring.redis.jedis.pool.max-idle=500
spring.redis.jedis.pool.time-between-eviction-runs-millis=30000 // 定时心跳保活与检测
spring.redis.jedis.pool.min-idle=500 // 连接池的稳定数量
spring.redis.jedis.pool.test-while-idle=true //定时心跳保活与检测
spring.redis.jedis.pool.num-tests-per-eviction-run=-1 // 每次保活检测, 都需要把500个连接都检测一遍. 如果设置为-2, 则每次检测1/2比例的的连接.
spring.redis.jedis.pool.min-evictable-idle-time-millis=-1 // 不要因为idleTime大于某个阈值从而把连接给删除掉. 这样可以防止无意义的大规模连接重建。
效果验证
maxBorrowWaitTimeMills 下降比例接近 80%
createdCount 也从之前的 11555次 下降到了 500次(即池子初始化的size)
阿里云开发者社区,千万开发者的选择
阿里云开发者社区,百万精品技术内容、千节免费系统课程、丰富的体验场景、活跃的社群活动、行业专家分享交流,欢迎点击【阅读原文】加入我们。
文章引用微信公众号"阿里开发者",如有侵权,请联系管理员删除!