Jedis使用中常見的客戶端異常情況(匯總)

本篇文章給大家介紹一下redis常見客戶端異常匯總(jedis篇)。有一定的參考價值,有需要的朋友可以參考一下,希望對大家有所幫助。

Jedis使用中常見的客戶端異常情況(匯總)

【導讀】Jedis是redisJava版本的客戶端實現。在Redis客戶端的使用過程中,無論是客戶端使用不當或者Redis服務端出現問題,客戶端會反應出一些異常,本文分析了Jedis使用過程中常見的異常情況。【相關推薦:Redis視頻教程

一、無法從連接池獲取到連接

JedisPool中的Jedis對象個數是有限的,默認是8個。這里假設使用的默認配置,如果有8個Jedis對象被占用,并且沒有歸還,如果調用者還要從JedisPool中借用Jedis,就需要進行等待(例如設置了maxWaitMillis>0),如果在maxWaitMillis時間內仍然無法獲取到Jedis對象就會拋出如下異常。

redis.clients.jedis.exceptions.JedisConnectionException:?Could?not?get?a?resource?from?the?pool ?… Caused?by:?java.util.NoSuchElementException:?Timeout?waiting?for?idle?object ?at?org.apache.commons.pool2.impl.GenericObjectPool.borrowObject(GenericObjectPool.java:449)

還有一種情況,就是設置了blockWhenExhausted=false,那么調用者發現池子中沒有資源時,會立即拋出異常不進行等待,下面的異常就是blockWhenExhausted=false時的效果。

redis.clients.jedis.exceptions.JedisConnectionException:?Could?not?get?a?resource?from?the?pool ?… Caused?by:?java.util.NoSuchElementException:?Pool?exhausted ?at?org.apache.commons.pool2.impl.GenericObjectPool.borrowObject(GenericObjectPool.java:464)

對于這個問題,需要重點討論的是為什么連接池沒有資源了,造成沒有資源的可能的原因非常多

1.客戶端:高并發下連接池設置過小,出現供不應求,所以會出現上面的錯誤,但是正常情況下只要比默認的最大連接數(8個)多一些即可,因為正常情況下JedisPool以及Jedis的處理效率足夠高。

2.客戶端:沒有正確使用連接池,比如沒有進行釋放,例如下面代碼所示:定義JedisPool,使用默認的連接池配置。

GenericObjectPoolConfig?poolConfig?=?new?GenericObjectPoolConfig(); JedisPool?jedisPool?=?new?JedisPool(poolConfig,?"127.0.0.1",?6379); //向JedisPool借用8次連接,但是沒有執行歸還操作。 for?(int?i?=?0;?i?<p>當調用者再向連接池借用Jedis時(如下操作),就會拋出異常:</p><p>jedisPool.getResource().ping();</p><p>3.客戶端:存在慢查詢操作,這些慢查詢持有的Jedis對象歸還速度會比較慢,造成池子滿了。</p><p>4.服務端:客戶端是正常的,但是Redis服務端由于一些原因造成了客戶端命令執行過程的阻塞,也會使得客戶端拋出這種異常。可以看到造成這個異常的原因是多個方面的,不要被異常的表象所迷惑,而且并不存在萬能鑰匙能解決所有問題,開發和運維只能不斷加強對于Redis的理解,順藤摸瓜逐漸找到問題所在。</p><p><strong>二、 客戶端讀寫超時</strong></p><p>Jedis在調用Redis時,如果出現了讀寫超時后,會出現下面的異常:</p><pre class="brush:js;toolbar:false;">redis.clients.jedis.exceptions.JedisConnectionException:?java.net.SocketTimeoutException:?Read?timed?out

造成該異常的原因也有以下幾種:

讀寫超時設置的過短。
命令本身就比較慢。
客戶端與服務端網絡不正常。
Redis自身發生阻塞。

三、客戶端連接超時

Jedis在調用Redis時,如果出現了讀寫超時后,會出現下面的異常:

redis.clients.jedis.exceptions.JedisConnectionException:?java.net.SocketTimeoutException:?connect?timed?out

造成該異常的原因也有以下幾種:

連接超時設置的過短。
Redis發生阻塞,造成tcp-backlog已滿,造成新的連接失敗。
客戶端與服務端網絡不正常。

四、客戶端緩沖區異常

Jedis在調用Redis時,如果出現客戶端數據流異常,會出現下面的異常。

redis.clients.jedis.exceptions.JedisConnectionException:?Unexpected?end?of?stream.

造成這個異常原因可能有如下幾種:

1.輸出緩沖區滿。例如將普通客戶端的輸出緩沖區設置為1M 1M 60:

config?set?client-output-buffer-limit?"normal?1048576?1048576?60?slave?268435456?67108864?60?pubsub?33554432?8388608?60"

如果使用get命令獲取一個bigkey(例如3M),就會出現這個異常。

2.長時間閑置連接被服務端主動斷開,可以查詢timeout配置的設置以及自身連接池配置是否需要做空閑檢測。

3.不正常并發讀寫:Jedis對象同時被多個線程并發操作,可能會出現上述異常。

五、lua腳本正在執行

如果Redis當前正在執行Lua腳本,并且超過了lua-time-limit,此時Jedis調用Redis時,會收到下面的異常。對于如何處理這類問題(Lua lua-time-limit配置之前章節已經介紹了)

redis.clients.jedis.exceptions.JedisDataException: BUSY Redis is busy running a script. You can only call SCRIPT KILL or SHUTDOWN NOSAVE.

六、Redis正在加載持久化文件

Jedis調用Redis時,如果Redis正在加載持久化文件,那么會收到下面的異常。

redis.clients.jedis.exceptions.JedisDataException:?LOADING?Redis?is?loading?the?dataset?in?memory

七、Redis使用的內存超過maxmemory配置

Jedis調用Redis執行寫操作時,如果Redis的使用內存大于maxmemory的設置,會收到下面的異常,此時應該調整maxmemory并找到造成內存增長的原因(maxmemory之前章節已經介紹了)

redis.clients.jedis.exceptions.JedisDataException:?OOM?command?not?allowed?when?used?memory?&gt;?'maxmemory'.

八、客戶端連接數過大

如果客戶端連接數超過了maxclients,新申請的連接就會出現如下異常:

redis.clients.jedis.exceptions.JedisDataException:?ERR?max?number?of?clients?reached

此時新的客戶端連接執行任何命令,返回結果都是如下:

127.0.0.1:6379&gt;?get?hello (error)?ERR?max?number?of?clients?reached

這個問題可能會比較棘手,因為此時無法執行Redis命令,一般來說可以從兩個方面進行著手。

1.客戶端:如果maxclients參數不是很小的話,應用方的客戶端連接數基本不會超過maxclients,通常來看是由于應用方對于Redis客戶端使用不當造成的。此時如果應用方是分布式結構的話,可以通過下線部分應用節點(例如占用連接較多的節點),使得Redis的連接數先降下來。從而讓絕大部分節點可以正常運行,此時在再通過查找程序bug或者調整maxclients進行問題的修復。

2.服務端:如果此時客戶端無法處理,而當前Redis為高可用模式(例如Redis sentinel和Redis Cluster),可以考慮將當前Redis做故障轉移。

此問題不存在確定的解決方式,但是無論從哪個方面進行處理,故障的快速恢復極為重要,當然更為重要的是找到問題的所在,否則一段時間后客戶端連接數依然會超過maxclients。

附贈GenericObjectPoolConfig的重要屬性Jedis使用中常見的客戶端異常情況(匯總)

Jedis使用中常見的客戶端異常情況(匯總)

原文地址:https://mp.weixin.qq.com/s?__biz=MjM5NTk0MTM1Mw==&amp;mid=2650650677&amp;idx=1&amp;sn=cbb1cb9fefdf9641a4a7c775660114e8&amp;chksm=bef9c6b3898e4fa5a31ac6e572dca4c20a37d6c1dcb41004d831b34300c5c9ae0ed8c3a1bb45&amp;scene=21#wechat_redirect  作者:付磊

更多編程相關知識,請訪問:Redis視頻教程!!

? 版權聲明
THE END
喜歡就支持一下吧
點贊9 分享