首頁  >  文章  >  資料庫  >  Jedis使用中常見的客戶端異常情況(總結)

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

青灯夜游
青灯夜游轉載
2021-05-28 11:23:102856瀏覽

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

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

【導讀】Jedis是Redis的java版本的客戶端實作。在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 < 8; i++) {
    Jedis jedis = null;
    try {
 jedis = jedisPool.getResource();
 jedis.ping();
    } catch (Exception e) {
 e.printStackTrace();
    }
}

當呼叫者再向連接池借用Jedis時(如下操作),就會拋出異常:

jedisPool.getResource().ping();

3.客戶端:存在慢查詢操作,這些慢查詢所持有的Jedis物件歸還速度會比較慢,造成池子滿了。

4.服務端:客戶端是正常的,但是Redis服務端由於一些原因造成了客戶端命令執行過程的阻塞,也會使得客戶端拋出這種異常。可以看到造成這個異常的原因是多方面的,不要被異常的表象所迷惑,而且並不存在萬能鑰匙能解決所有問題,開發和運維只能不斷加強對於Redis的理解,順藤摸瓜逐漸找到問題所在。

二、客戶端讀寫超時

Jedis在呼叫Redis時,如果出現了讀寫逾時後,會出現下面的異常:

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 > &#39;maxmemory&#39;.

#八、客戶端連接數過大

############################################如果客戶端連線數超過了maxclients,新申請的連線就會出現如下例外:###
redis.clients.jedis.exceptions.JedisDataException: ERR max number of clients reached
###此時新的用戶端連線執行任何指令,回傳結果都是如下:###
127.0.0.1:6379> 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使用中常見的客戶端異常情況(總結)

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

作者:付磊

更多编程相关知识,请访问:编程教学!!

以上是Jedis使用中常見的客戶端異常情況(總結)的詳細內容。更多資訊請關注PHP中文網其他相關文章!

陳述:
本文轉載於:segmentfault.com。如有侵權,請聯絡admin@php.cn刪除