jedis 引起服务器假死

问题描述:

记一次jedis导致服务器假死的解决方案
2020.9.20 20:00左右
加油贝线上商城出现连接失败,所有客户端出现页面转圈问题,上午就出现了两次,当时没有解决,直接重启,傍晚又来一次,不行了,群里炸锅了.


原因分析:

先介绍一下服务器配置,4核16g带宽3m的服务器(后面用的到)
先打开xshell,连接到服务器,查看服务进程是否存在,一看进程,还在,那就有的解决,开心的一批😄,开始着手排查,先top 查看cpu占用,发现cpu利用率百分一都不到,内存也是正常,此时心里有点波动,那就继续看看是不是死循环或者是死锁的问题,排查线程,top -Hp -pid 查看进程下所有线程状态,发现所有线程尽然全部阻塞,只好放大招了 jstack -pid 生成线程快照

java.lang.Thread.State: WAITING (parking)
at sun.misc.Unsafe.park(Native Method)
- parking to wait for <0x00000006addee0c8> (a java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject)
at java.util.concurrent.locks.LockSupport.park(LockSupport.java:186)
at java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject.await(AbstractQueuedSynchronizer.java:2043)
at org.apache.commons.pool2.impl.LinkedBlockingDeque.takeFirst(LinkedBlockingDeque.java:524)
at org.apache.commons.pool2.impl.GenericObjectPool.borrowObject(GenericObjectPool.java:433)
at org.apache.commons.pool2.impl.GenericObjectPool.borrowObject(GenericObjectPool.java:360)
at redis.clients.util.Pool.getResource(Pool.java:40)
at redis.clients.jedis.JedisPool.getResource(JedisPool.java:84)
at com.sohu.snscommon.cluster.service.impl.OrMetaRedisClusterServiceImpl.getJd(OrMetaRedisClusterServiceImpl.java:111)
at com.sohu.snscommon.cluster.service.impl.OrMetaRedisClusterServiceImpl.getItem(OrMetaRedisClusterServiceImpl.java:241)
at com.sohu.sns_protobuf.service.impl.SnsProtoCacheServerImpl.loadCache(SnsProtoCacheServerImpl.java:44)
at com.sohu.sns_protobuf.service.impl.SnsPersServerImpl.loadItemJson(SnsPersServerImpl.java:167)
at com.sohu.sns_protobuf.utils.PersistenceUtil.getItem(PersistenceUtil.java:109)
at com.sohu.sns.service.pull.service.FeedPullService.getUserRelation(FeedPullService.java:215)
at com.sohu.sns.service.pull.service.FeedPullService.addPullMarkInternal(FeedPullService.java:172)
at com.sohu.sns.service.pull.service.FeedPullService.addPullMark(FeedPullService.java:153)
at com.sohu.sns.service.pull.mq.PullServerMQConsumer$1.run(PullServerMQConsumer.java:92)
at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:471)
at java.util.concurrent.FutureTask.run(FutureTask.java:262)
at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.access$201(ScheduledThreadPoolExecutor.java:178)
at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(ScheduledThreadPoolExecutor.java:292)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615)
at java.lang.Thread.run(Thread.java:744)

发现是jedisPool.getRecouce阻塞了,原来是jedis的问题,既然知道是什么,那就开始解决,


解决方案:

项目依赖
		<dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-redis</artifactId>
            <exclusions>
                <exclusion>
                    <groupId>io.lettuce</groupId>
                    <artifactId>lettuce-core</artifactId>
                </exclusion>
            </exclusions>
        </dependency>
		<dependency>
		      <groupId>redis.clients</groupId>
		      <artifactId>jedis</artifactId>
		      <version>2.9.0</version>
		 </dependency>
发现是jedisPool.getRecouce阻塞了,原来是jedis的问题,既然知道是什么,那就开始解决, 看一下配置文件,发现有问题了 max-wait: -1ms 获取不到recource尽然要一直阻塞
    jedis:
      pool:
        max-active: 8 # 连接池最大连接数(使用负值表示没有限制)
        max-wait: -1ms # 连接池最大阻塞等待时间(使用负值表示没有限制)
        max-idle: 8 # 连接池中的最大空闲连接
        min-idle: 0 # 连接池中的最小空闲连接
现在开始调配jedis
    jedis:
      pool:
        max-active: 4 # 连接池最大连接数(使用负值表示没有限制)
        max-wait: 50ms # 连接池最大阻塞等待时间(使用负值表示没有限制)
        max-idle: 4 # 连接池中的最大空闲连接
        min-idle: 2 # 连接池中的最小空闲连接
这是调整后的配置 简单说一下这个配置的依据,之前服务器的配置是4核16g3m的,线程最大数是 核数4 由于redis涉及到io操作,核数就是线程数,当线程不涉及到io操作时,线程数可以设置为 核数*2+1 ,最小空闲呢就根据需求设置,这里我选择用2个线程 再次上线,问题解决 注意: 用jedis就要对jedis配置熟悉,避免不需要的麻烦

此时还有一种解决方案,这种解决方案是可以用lettuce 来带替jedis,springboot2.1.3默认的spring-boot-starter-data-redis默认实现就是lettuce

到此为止,从排查到结束没用20分钟就解决了问题,对大家要是有所帮助,帮忙点个赞,关注一下公众号,谢谢啦😊

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值