jedis参数不当引起的问题总结

jedis参数不当引起dubbo服务线程池耗尽异常

现象:一个dubbo服务偶发性的出现个别机器甚至整个集群大量报线程池耗尽的问题。一开始对问题的处理比较粗暴,直接增长了10倍的线程数。可是问题依然偶尔出现,重启服务就能够暂时解决。后来,发现问题出现频率有点高,不得不花点时间认真分析了。java

实际缘由:jedis参数设置不当。实际仔细分析问题后发现每次出现异常最开始都是出现了大量的jedis链接池获取链接异常:redis

redis.clients.jedis.exceptions.JedisConnection: Could not get a resource from the pool
...省略其余堆栈信息
Caused by: redis.clients.jedis.exceptions.JedisConnectionException: java.net.SocketTimeoutException: connect time out
...省略其余堆栈信息

而这些time out实际是redis节点故障或者网络抖动引发的。而后看看jedis配置,timeout设置为1000,maxRedirect为2,因此一旦出现redis链接问题,将会致使请求阻塞3s左右。而此服务的qps分摊到单机约为200,阻塞致使了dubbo请求的堆积,进而致使雪崩。处理方法:缩短timeout;去除redirect;根据业务请求考虑增长熔断组件。网络

另外经过jstack分析,发现一旦出dubbo线程池耗尽的问题,大量的dubbo处理线程都是处于WAITING(parking)状态,卡顿在获取redis链接。分析jedis链接管理相关代码,jedis链接池使用ReentrantReadWriteLock管理,获取链接涉及锁资源的争夺,而redis server节点没法链接将致使链接池须要尝试建立新的链接,这个过程会拿走写锁,致使其余须要经过读锁获取链接的线程进入等待。因此 也须要根据qps设置maxTotal(这个出现问题的jedis竟然设置的链接数为10!)。spa

spark服务使用jedis访问redis致使redis服务毛刺

咱们所使用的redis cluster集群是个比较大集群,具备数十个节点,集群的读写压力都至关大。其中一部分读写操做来自其余同事维护的spark服务,使用jedis访问。.net

现象:发现redis的响应时间出现有规律的毛刺。 DBA排查发现redis集群的一个节点的负载相对于其余节点比较高,并且出现大量的cluster slots命令。线程

分析:分析jedis源码,jedis每次初始化建立链接都是从第一个节点开始尝试并执行cluster slots命令来获取整个redis cluster集群的拓扑信息;若是jedis链接池获取的链接失效,也会执行renewSlotCache,renewClotCache也是会执行cluster slots命令的。 通过推断及分析,问题出在spark使用jedis的模式上,spark每一个批次任务都会建立新的jedis链接,批次处理完成即销毁掉,因此spark任务执行过程当中会反复执行jedis链接池的初始化进而执行cluster slots命令,而从DBA了解到cluster slots命令是比较耗资源的,因此致使了第一个节点负载比较高(jedis链接串固定的,因此第一个节点老是被执行cluster slots命令)。code

处理:经过打散jedis链接串上节点的顺序来避免老是固定的第一个节点被用来执行cluster slots。此方法实施后,毛刺确实消失了。server

疑问:上述方法能够说只是缓解了redis节点负载不均衡的问题,可是因为对spark使用不太了解,因此暂时不知道是否有办法在多个批次任务间共享jedis链接。资源

相关文章
相关标签/搜索