本篇文章跟大家介紹一下Redis常見客戶端異常匯總(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 > 'maxmemory'.
#八、客戶端連接數過大
############################################如果客戶端連線數超過了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的重要属性
原文地址:https://mp.weixin.qq.com/s?__biz=MjM5NTk0MTM1Mw==&mid=2650650677&idx=1&sn=cbb1cb9fefdf9641a4a7c775660114e8&chksm=bef9c6b3898e4fa5a31ac6e572dca4c20a37d6c1dcb41004d831b34300c5c9ae0ed8c3a1bb45&scene=21#wechat_redirect 作者:付磊
更多编程相关知识,请访问:编程教学!!
以上是Jedis使用中常見的客戶端異常情況(總結)的詳細內容。更多資訊請關注PHP中文網其他相關文章!