記redis一次Could not get a resource from the pool 異常的解決過程


最近有個項目中的redis每天都會報 "Could not get a resource from the pool"的錯誤,而這套代碼在另一地方部署又沒有問題。一直找不到錯誤原因。按字面意思是連接池中資源不夠。

1. 有可能是並發太高而連接池太小,嘗試修改連接池上限來解決問題,修改方法如下:

  <!-- redis連接池的配置 -->
  <bean id="jedisPoolConfig" class="redis.clients.jedis.JedisPoolConfig">
    <property name="maxTotal" value="${spring.redis.maxTotal}"/>
    <property name="maxIdle" value="${spring.redis.maxIdle}"/>
    <property name="minIdle" value="${spring.redis.minIdle}"/>
    <property name="testOnBorrow" value="${spring.redis.testOnBorrow}"/>
    <property name="testOnReturn" value="${spring.redis.testOnReturn}"/>
  </bean>

修改 maxTotal 到 60 100 300,可以改變連接池大小

spring.redis.maxTotal=8
spring.redis.maxIdle=8
spring.redis.minIdle=1
spring.redis.testOnBorrow=true
spring.redis.testOnReturn=true

將連接池上限修改到很大,運行后發現還是沒有解決,仍然報錯,有時還會報 "clusterdown the cluster is down"。將maxIdle與minIdle調大,也是一樣沒有效果。

2. 有網友說有可能是redis連接沒有被釋放,連接池設再大也沒用。項目使用了spring-data-redis,按理釋放是不需要自己處理的,項目使用的配置如下:

  <bean id="redisTemplate" class="org.springframework.data.redis.core.RedisTemplate">
    <property name="connectionFactory" ref="jedisConnectionFactory" />
    <property name="keySerializer" ref="stringRedisSerializer" />
    <property name="hashKeySerializer" ref="stringRedisSerializer" />
    <property name="valueSerializer" ref="stringRedisSerializer"/> 
  </bean>

這里並沒有使用redis事務功能,默認情況下 RedisTemplate 的 enableTransactionSupport = false, 所以不需要手動釋放連接。

關於開啟事務后手動釋放的代碼,參考這里(https://www.cnblogs.com/DDgougou/p/10268206.html)

3.網上有網友說有可能是jedis版本的問題,當前項目使用的版本為:

    <dependency>
      <groupId>redis.clients</groupId>
      <artifactId>jedis</artifactId>
      <version>2.9.0</version>
    </dependency>

更新到2.9.3,繼續測試。

    <dependency>
      <groupId>redis.clients</groupId>
      <artifactId>jedis</artifactId>
      <version>2.9.3</version>
    </dependency>

測試發現,提示終於有變化了,不再顯示"Could not get a resource from the pool",但問題還是沒有解決,因為項目使用集群的原因,變成提示"Too many Cluster redirections",這是什么鬼???確實沒有了連接池的錯誤提示,但又出現新的問題。

4. 檢查redis集群,"Too many Cluster redirections"的意思是連不上其中一個節點,嘗試連另一個配置的節點,如果都連不上,就會提示這個錯誤。檢查redis集群方法如下:

利用redis-cli命令進行遠程檢查

redis-cli -h 127.0.0.1 -p 9000
// 連接成功 如果設置了密碼,需要運行命令  auth xxx   xxx為密碼
運行 cluster info 檢查

執行結果,集群正常

xxx:9000> cluster info
cluster_state:ok
cluster_slots_assigned:16384
cluster_slots_ok:16384
cluster_slots_pfail:0
cluster_slots_fail:0
cluster_known_nodes:6
cluster_size:3
cluster_current_epoch:187
cluster_my_epoch:186
cluster_stats_messages_sent:111466490
cluster_stats_messages_received:111459674
(1.53s)

集群沒問題,但總會偶爾連不上,因為把做了3個節點(redis與mysql裝在同一台服務器上),全連不上的機率不大,所以最大的可能就是服務器或者服務器的網絡出問題,造成"Too many Cluster redirections"這個錯誤的發生。

最后通過觀察發現出錯的規律,當mysql在執行一個很耗時的存儲過程CPU高得飛起時,就很容易出現報錯的情況。最終基本確定是服務器突然卡引起的異常,所以才會一會正常偶爾又會報錯。

經過一天的驗證與解決,出現"Could not get a resource from the pool"進的解決方法總結如下:

1. 參數問題,有可能是連接池太小引起

2. jedis版本問題引起

3.服務器性能引起

最終把redis移到另一台服務器上,問題解決。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM