相关推荐recommended
详细解决redis.clients.jedis.exceptions.JedisConnectionException: Could not get a resource from the pool
作者:mmseoamin日期:2024-01-30

文章目录

  • 1. 复现错误
  • 2. 分析错误
  • 3. 解决错误
  • 4. 解决此错误的其他办法

    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.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的配置也没有问题。

    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即可,如下图所示:

    详细解决redis.clients.jedis.exceptions.JedisConnectionException: Could not get a resource from the pool,在这里插入图片描述,第1张

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

    详细解决redis.clients.jedis.exceptions.JedisConnectionException: Could not get a resource from the pool,在这里插入图片描述,第2张

    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
    

    详细解决redis.clients.jedis.exceptions.JedisConnectionException: Could not get a resource from the pool,在这里插入图片描述,第3张

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

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

    config get maxclients
    

    详细解决redis.clients.jedis.exceptions.JedisConnectionException: Could not get a resource from the pool,在这里插入图片描述,第4张

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

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