zl程序教程

您现在的位置是:首页 >  数据库

当前栏目

详细解决redis.clients.jedis.exceptions.JedisConnectionException: Could not get a resource from the pool

Redis 解决 详细 The not from get could
2023-09-27 14:26:20 时间

1. 复现错误


今天从gitlab上下载本公司的项目,但在启动时报出如下错误:

org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'redisKeyExpirationListener' defined in file [D:\Software\...\RedisKeyExpirationListener.class]: Invocation of init method failed; nested exception is org.springframework.data.redis.RedisConnectionFailureException: Cannot get Jedis connection; nested exception is redis.clients.jedis.exceptions.JedisConnectionException: Could not get a resource from the pool
	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1628)
	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:555)
	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:483)
	at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:306)
	at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:230)
	at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:302)
	at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:197)
	at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:761)
	at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:866)
	......
Caused by: org.springframework.data.redis.RedisConnectionFailureException: Cannot get Jedis connection; nested exception is redis.clients.jedis.exceptions.JedisConnectionException: Could not get a resource from the pool
	at org.springframework.data.redis.connection.jedis.JedisConnectionFactory.fetchJedisConnector(JedisConnectionFactory.java:198)
	at org.springframework.data.redis.connection.jedis.JedisConnectionFactory.getConnection(JedisConnectionFactory.java:345)
	at org.springframework.data.redis.listener.KeyspaceEventMessageListener.init(KeyspaceEventMessageListener.java:80)
	at org.springframework.data.redis.listener.KeyspaceEventMessageListener.afterPropertiesSet(KeyspaceEventMessageListener.java:132)
	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.invokeInitMethods(AbstractAutowireCapableBeanFactory.java:1687)
	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1624)
	... 59 more
Caused by: redis.clients.jedis.exceptions.JedisConnectionException: Could not get a resource from the pool
	at redis.clients.util.Pool.getResource(Pool.java:53)
	at redis.clients.jedis.JedisPool.getResource(JedisPool.java:226)
	at redis.clients.jedis.JedisPool.getResource(JedisPool.java:16)
	at org.springframework.data.redis.connection.jedis.JedisConnectionFactory.fetchJedisConnector(JedisConnectionFactory.java:191)
	... 64 more
Caused by: redis.clients.jedis.exceptions.JedisConnectionException: java.net.SocketTimeoutException: connect timed out
	at redis.clients.jedis.Connection.connect(Connection.java:207)
	at redis.clients.jedis.BinaryClient.connect(BinaryClient.java:93)
	at redis.clients.jedis.BinaryJedis.connect(BinaryJedis.java:1767)
	at redis.clients.jedis.JedisFactory.makeObject(JedisFactory.java:106)
	at org.apache.commons.pool2.impl.GenericObjectPool.create(GenericObjectPool.java:868)
	at org.apache.commons.pool2.impl.GenericObjectPool.borrowObject(GenericObjectPool.java:435)
	at org.apache.commons.pool2.impl.GenericObjectPool.borrowObject(GenericObjectPool.java:363)
	at redis.clients.util.Pool.getResource(Pool.java:49)
	... 67 more
Caused by: java.net.SocketTimeoutException: connect timed out
	at java.net.DualStackPlainSocketImpl.waitForConnect(Native Method)
	at java.net.DualStackPlainSocketImpl.socketConnect(DualStackPlainSocketImpl.java:85)
	at java.net.AbstractPlainSocketImpl.doConnect(AbstractPlainSocketImpl.java:350)
	at java.net.AbstractPlainSocketImpl.connectToAddress(AbstractPlainSocketImpl.java:206)
	at java.net.AbstractPlainSocketImpl.connect(AbstractPlainSocketImpl.java:188)
	at java.net.PlainSocketImpl.connect(PlainSocketImpl.java:172)
	at java.net.SocksSocketImpl.connect(SocksSocketImpl.java:392)
	at java.net.Socket.connect(Socket.java:589)
	at redis.clients.jedis.Connection.connect(Connection.java:184)
	... 74 more

具体的错误信息为redis.clients.jedis.exceptions.JedisConnectionException: Could not get a resource from the pool

2. 分析错误


根据上述报错信息可知,这是redis出现了错误。

  1. 首先,检查我的redis的配置信息,如下代码所示:
########################################
###
### 2.redis的配置
###
########################################
cache:
  redis:
    db: 12
    enable: true
    hostName: 127.0.0.1
    password: test
    port: 6379

据此可以看出,我的redis配置没有问题。

  1. redis配置既然没有问题,则去检查Jedis ConnectionFactory的配置是否存在问题,如下代码所示:
<!-- Jedis ConnectionFactory -->
<bean id="jedisConnectionFactory" class="org.springframework.data.redis.connection.jedis.JedisConnectionFactory">
    <property name="hostName" value="${cache.redis.hostName}"/>
    <property name="port" value="${cache.redis.port}"/>
    <property name="password" value="${cache.redis.password}"/>
    <property name="database" value="${cache.redis.db}"/>
    <property name="usePool" value="true"/>
    <property name="poolConfig">
        <!-- jedisPoolConfig -->
        <bean class="redis.clients.jedis.JedisPoolConfig">
            <property name="maxTotal" value="100"/>
            <property name="minIdle" value="20"/>
            <property name="maxWaitMillis" value="10000"/>
        </bean>
    </property>
</bean>

由上代码所示,Jedis ConnectionFactory的配置也没有问题。

  1. 继续分析错误信息,错误信息说Error creating bean with name 'redisKeyExpirationListener'...,即无法创建redisKeyExpirationListener的bean对象,则去检查RedisKeyExpirationListener类,如下代码所示:
/**
 * @author super先生
 * @datetime 2023/3/12 16:30
 * @desc  这是对redis key过期的监听器
 */
@Component
@Conditional({RedisCondition.class})
public class RedisKeyExpirationListener extends KeyExpirationEventMessageListener {
  private Logger LOG = LoggerFactory.getLogger(this.getClass());

  @Autowired
  private StringRedisTemplate redisTemplate;
  @Autowired
  private ProjectDao projectDao;

  public RedisKeyExpirationListener(RedisMessageListenerContainer listenerContainer) {
      super(listenerContainer);
  }

  @Override
  public void onMessage(Message message, byte[] pattern) {
      String key = message.toString();
      LOG.info("{} 缓存已到期", key);

      String[] split = key.split("_");
      if ("timer".equals(split[1])) {
          //
          if (!redisTemplate.hasKey(split[0])) {
              // 如果没有key,删除定时器key
              redisTemplate.delete(key);
              LOG.info("{} 对应的数据不存在,已删除", key);
              return;
          }
          String value = redisTemplate.opsForValue().get(split[0]);
          DashboardBoard dashboardBoard = JSONObject.parseObject(value, DashboardBoard.class);
          if (dashboardBoard == null) {
              // 重新设置key
              redisTemplate.opsForValue().set(split[0] + "_timer", "", 5, TimeUnit.MINUTES);
              LOG.info("{} 缓存重设", split[0]);
              return;
          }

          try {
              projectDao.update(dashboardBoard);
              redisTemplate.delete(split[0]);
              LOG.info("数据持久化, {} 缓存删除", split[0]);
          } catch (Exception e) {
              e.printStackTrace();
              // 重新设置key
              redisTemplate.opsForValue().set(split[0] + "_timer", "", 5, TimeUnit.MINUTES);
              LOG.info("{} 缓存重设", split[0]);
          }
      }
  }
}

经过对RedisKeyExpirationListener类的检查,没有返现任何问题。

  1. 继续分析上述错误,直至看到connect timed out错误信息。

connect timed out表示连接超时,也就是说,我的redis没有启动。

我经过反复检查后,发现我的redis确实没有启动。

3. 解决错误


由于我没有启动redis,启动redis即可,如下图所示:

在这里插入图片描述

重新启动项目,即可成功运行,如下图所示:

在这里插入图片描述

4. 解决此错误的其他办法


我的是因为没有启动redis,导致了这个错误:Could not get a resource from the pool

如果你的redis启动了,但仍报出这个错误,可以参考如下解决方法,来解决你的错误:

  1. 检查redis是否崩溃(宕机)。

  2. 检查redis的连接池

输入如下命令,进入redis服务器:

./redis-cli -h 127.0.0.1 -p 6379 -a passwd

输入如下命令,查看当前连接数:

INFO clients

在这里插入图片描述

  1. 检查redis服务器的最大连接数配置,如果需要,请将其增加。

输入如下命令,查看最大连接数:

config get maxclients

在这里插入图片描述

  1. 检查网络连接是否正常,并确保防火墙未阻止连接。

  2. 检查redis服务器的配置文件和协议是否正确。