redis 獲取連接池連接不上問題


問題詳情:

redis.clients.jedis.exceptions.JedisConnectionException: Could not get a resource from the pool>
2017-12-21 13:50:58,192 WARN [com.inspeeding.StoreUploadFileToInThread] Thread-8 - <start again.....>
redis.clients.jedis.exceptions.JedisConnectionException: Could not get a resource from the pool
        at redis.clients.util.Pool.getResource(Pool.java:50)
        at redis.clients.jedis.JedisSentinelPool.getResource(JedisSentinelPool.java:181)
        at com.inspeeding.util.IntranetRedisUtil2.rpop(IntranetRedisUtil2.java:262)
        at com.inspeeding.StoreUploadFileToInThread.server(StoreUploadFileToInThread.java:83)
        at com.inspeeding.StoreUploadFileToInThread.run(StoreUploadFileToInThread.java:67)
Caused by: java.util.NoSuchElementException: Unable to validate object
        at org.apache.commons.pool2.impl.GenericObjectPool.borrowObject(GenericObjectPool.java:502)
        at org.apache.commons.pool2.impl.GenericObjectPool.borrowObject(GenericObjectPool.java:361)
        at redis.clients.util.Pool.getResource(Pool.java:48)
        ... 4 more

問題原因分析:

redis是我們數據的保管者,我們可以隨時存隨時取,大的小的,重要的不重要的,它都毫無怨言的幫我們保存着,甚至有些時候,我們變得很懶,存東西進去的時候順便還貼張紙:“過了一個星期就幫我扔了吧”,對於這些,Redis也都默默的接受了(誰叫Antirez把redis設計的這么好呢)。

這次要寫的就是關於這張留言紙的事。

Redis提供了一套“美好”的過期數據清理機制:
主動過期: Redis對數據是惰性過期,當一個key到了過期時間,Redis也不會馬上清理,但如果這個key過期后被再次訪問,Redis就會主動將它清理掉。
被動過期: 如果過期的Key一直沒被訪問,Redis也不會一直把它放那不管,它會每秒10次的執行以下的清理工作:
        隨機從所有帶有過期時間的Key里取出20個
        如果發現有過期的,就清理
        如果這里有25%的Key都是過期的,就繼續回到第一步再來一次

這套過期機制設計的很贊,可以這樣理解:如果當前有超過1/4的Key是過期的話,就不停地清理,直到只剩下1/4不到的Key是要過期的為止,然后就慢慢地隨機抽查着清理。



這個錯誤是因為JedisPool拿到一個連接后,調用 jedis.ping() 方法沒有得到正確的返回”pong”消息,而出現這個問題時,並不是traffic的高峰期,redis的cpu不高,於是程序員很快就懷疑到網絡上,難道有”丟包”?

但跑了幾天,發現出錯的時間固定在某幾個時間點(如晚上9點~10點),莫非是掃地阿姨每天定時在機房打掃衛生,碰着網線了?(有時候不得不佩服程序員的想象力)

然而在一個夜黑風高的晚上,程序員的腦子在這個時候一般是最清醒的,這時告警短信又來了,打開redis監控,像在唯品會上逛街一樣,對着redis的各項監控數據逛啊逛,突然,看到有幾條Expires的數據,當時的表情只能用看到關注了幾天的商品上標了大大”0.1折”時的表情來形容。

接下來的事情,想必大家也都猜到個七七八八了,當然是下單搶購支付了,
腦子里一系列的運算,掐指一算: “這個時間點正好有一大批key過期”,而且都是大的Set集合,每個都有幾十萬的數據,再一算: “Redis里的大部分需要過期的key就是這些key”。

於是,答案有了,Redis進行被動過期清理時,發現怎么隨機,都有超過1/4的Key都是過期的,就忙着不停的刪啊刪,再加上又都是大集合的刪除,O(N)的操作復雜度,無奈,
等redis刪完時,客戶端那邊的命令都等超時了。

原因找到了,如何解決?看業務場景吧,對於我們的場景,
做法是將過期時間設長一點,然后把這些可以刪掉的Key標記一下,丟到一個后台線程那里分頁刪Set里的數據,這樣就算redis再做過期操作,也不會用太多的時間來刪除。

最后,稍稍總結下,對於大個的集合對象,放redis的時候需要額外注意,如果想依賴redis的過期,可能會造成過期時短暫的redis block。

所以,要善待redis數據,比如不用了就自己清理掉,不要等着redis來幫你

 

 

 

 

解決辦法:

解決辦法:
1:  
登錄redis :
redis-cli
127.0.0.1:6379>config set stop-writes-on-bgsave-error no

2:使用redis-cli修改rdb目錄
CONFIG SET dir /tmp/redis_data
CONFIG SET dbfilename temp.rdb
重啟redis-server,問題解決!但是需要每次啟動server都要修改rdb的路徑。

3:直接修改redis.conf文件

dir /tmp/redis_data    #./ -->  /tmp/redis_data
dbfilename temp.rdb   #

啟動redis服務

 


免責聲明!

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



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