1. 原因
當磁盤滿時,程序在調用Pool.getResource(),從jedis實例池pool里借用實例時,出現連接異常,沒有可用的jedis實例,異常log如下:
2013-11-17 21:59:37,155 ERROR [TransportFrameEncoderService:97] main - <redis.clients.jedis.exceptions.JedisConnectionException: Could not get a resource from the pool Caused by: java.util.NoSuchElementException: Timeout waiting for idle object |
至於為啥磁盤滿時,會拋ConnectionException異常,推測redis-server在同步數據到磁盤時出現異常,導致文件句柄連接的異常,同時也會拒絕了網絡客戶端的連接,如下:
MISCONF Redis is configured to save RDB snapshots, but is currently not able to persist on disk. Commands that may modify the data set are disabled. Please check Redis logs for details about the error; nested exception is redis.clients.jedis.exceptions.JedisDataException: MISCONF Redis is configured to save RDB snapshots, but is currently not able to persist on disk. Commands that may modify the data set are disabled. Please check Redis logs for details about the error.
2. 修改
2.1 客戶端優化修改
a、增加參數testOnReturn和testOnBorrow 為true,表示每次借用和歸還jedis實例時,強行判斷當前jedis實例是否可用 b、增加config.setWhenExhaustedAction(GenericObjectPool.WHEN_EXHAUSTED_GROW),表示每次pool中沒有可用的實例時,建新的jedis實例 c、修改邏輯:每次用完redis實例歸還時,如果當前redis壞掉就不用歸還,保證pool里面的實例都是可用的,代碼摘要如下: if (redis != null) { pool.returnResource(redis); }
2.2 服務端優化修改
由於redis中的熱點數據僅有臨時性的作用,所以在服務redis.conf配置文件中,禁用redis持久化功能,修改片段如下:
#save 900 1 #save 300 10 #save 60 10000 |
redisPool參數說明
maxActive:控制一個pool可分配多少個jedis實例,通過pool.getResource()來獲取;如果賦值為-1,則表示不限制;如果pool已經分配了maxActive個jedis實例,則此時pool的狀態就成exhausted了,在JedisPoolConfig maxIdle:控制一個pool最多有多少個狀態為idle的jedis實例; whenExhaustedAction:表示當pool中的jedis實例都被allocated完時,pool要采取的操作;默認有三種WHEN_EXHAUSTED_FAIL(表示無jedis實例時,直接拋出NoSuchElementException)、WHEN_EXHAUSTED_BLOCK(則表示阻塞住,或者達到maxWait時拋出JedisConnectionException)、WHEN_EXHAUSTED_GROW(則表示新建一個jedis實例,也就說設置的maxActive無用); maxWait:表示當borrow一個jedis實例時,最大的等待時間,如果超過等待時間,則直接拋出JedisConnectionException; testOnBorrow:在borrow一個jedis實例時,是否提前進行alidate操作;如果為true,則得到的jedis實例均是可用的; testOnReturn:在return給pool時,是否提前進行validate操作; testWhileIdle:如果為true,表示有一個idle object evitor線程對idle object進行掃描,如果validate失敗,此object會被從pool中drop掉;這一項只有在timeBetweenEvictionRunsMillis大於0時才有意義; timeBetweenEvictionRunsMillis:表示idle object evitor兩次掃描之間要sleep的毫秒數; numTestsPerEvictionRun:表示idle object evitor每次掃描的最多的對象數; minEvictableIdleTimeMillis:表示一個對象至少停留在idle狀態的最短時間,然后才能被idle object evitor掃描並驅逐;這一項只有在timeBetweenEvictionRunsMillis大於0時才有意義; softMinEvictableIdleTimeMillis:在minEvictableIdleTimeMillis基礎上,加入了至少minIdle個對象已經在pool里面了。如果為-1,evicted不會根據idle time驅逐任何對象。如果minEvictableIdleTimeMillis>0,則此項設置無意義,且只有在timeBetweenEvictionRunsMillis大於0時才有意義; lifo:borrowObject返回對象時,是采用DEFAULT_LIFO(last in first out,即類似cache的最頻繁使用隊列),如果為False,則表示FIFO隊列; |
參考
http://blog.csdn.net/freebird_lb/article/details/7460328
https://github.com/xetorthio/jedis/issues/206
http://www.cnblogs.com/linjiqin/archive/2013/06/14/3135248.html