redis使用連接池報錯解決
redis使用十幾小時就一直報異常
redis.clients.jedis.exceptions.JedisConnectionException: Could not get a resource from the pool at redis.clients.util.Pool.getResource(Pool.java:22) at com.derbysoft.jredis.longkeytest.BorrowObject.run(BorrowObject.java:22) at java.lang.Thread.run(Thread.java:662) Caused by: java.util.NoSuchElementException: Timeout waiting for idle object at org.apache.commons.pool.impl.GenericObjectPool.borrowObject(GenericObjectPool.java:1134) at redis.clients.util.Pool.getResource(Pool.java:20)
原因是沒有回收資源導致
正確的做法是
ShardedJedis jedis = shardedJedisPool.getResource(); try { jedis.set(key, value); } finally { shardedJedisPool.returnResource(jedis); }
更新內容:
如果你用的jedis 2.4.2以及以前版本,用完之后別忘了return連接到資源池。
不過2.5.0版本之后,jedis使用了try-with-resource,jedis用完了就會自動歸還了,不用每次都自己return了。
各種鏈接數的參數自己調一下。例如MaxTotal,MaxIdle等等~
如果redis server不在局域網內,可能會因為network問題導致鏈接超時,會拋出socket的異常,當然寫數據就也會丟失。
connection的timeout默認是2000ms,你可以自己調的大一些,這樣網絡慢的時候就不至於丟失數據。
十分重要的一點:在開發的時候,方法A調用方法B,方法A需要獲取jedis 鏈接,方法B也要獲取jedis鏈接,在實現的時候盡量讓他們公用連接,例如B用A的鏈接,這樣效率會快非常多,而且也不會浪費鏈接。
最重要的一點,從google老外回答:
1.I test it using a multi-thread code, when the poolSize > maxclients(redis.conf),
it will throw this exception. And it runs well when the maxclients is larger than poolSize.
2.If you set maxclients to 10, and set fixed thread pool size to 20, it prints ".. fail to get connection...".
If you set maxclients to 10, and set fixed thread pool size to 5, it runs well.
從而得之,在redis配置文件,redis.conf文件中,有個參數設置,maxclients(默認是注釋掉的,不設置此值時表示無redis客戶端連接個數限制)。
設置時,maxclients的值要大於poolSize(最大連接池的鏈接個數)。