【redis】常見JedisConnectionException異常分析

來源:互聯網
上載者:User

純屬用於筆記,轉自:http://blog.csdn.net/fachang/article/details/7984123


最近項目開發中用到了Redis, 選擇了官網推薦的java client Jedis。 Redis常用命令學習:http://redis.io/commands
Redis官方推薦Java用戶端Jedis(包含了所有Redis命令的實現):https://github.com/xetorthio/jedis

Jedis使用過程中最常見異常JedisConnectionException有時確實給我們帶來了很多困惑,這個異常通常出現在兩個使情境。

一、當我們執行如下JedisPool類執行個體的getResource()時拋出can't get a resource異常。

異常代碼如下:

redis.clients.jedis.exceptions.JedisConnectionException: Could not get a resource from the pool

at redis.clients.util.Pool.getResource(Pool.java:22)

分析:

redis.clients.util.Pool.getResource會從JedisPool執行個體池中返回一個可用的redis串連。分析源碼可知JedisPool extends redis.clients.util.Pool<Jedis> .而Pool<T>是通過

commons-pool開源工具包中的org.apache.commons.pool.impl.GenericObjectPool來實現對Jedis執行個體的管理的。所以我們分析一下GenericObjectPool或許能找到答案。 首先看一下common-pool的api:http://commons.apache.org/pool/apidocs/index.html?org/apache/commons/pool/impl/GenericObjectPool.html。
其中三個重要個幾個屬性是:
MaxActive: 可用串連執行個體的最大數目,為負值時沒有限制。
MaxIdle: 空閑串連執行個體的最大數目,為負值時沒有限制。Idle的執行個體在使用前,通常會通過org.apache.commons.pool.BasePoolableObjectFactory<T>的activateObject()方法使其變得可用。
MaxWait: 等待可用串連的最大數目,單位毫秒(million seconds)。
     (注:pool.getResource()方法實際調用的GenericObjectPool類borrowObject()方法,該方法會根據MaxWait變數值在沒有可用串連(idle/active)時阻塞等待知道逾時,具體含義參看api。)

也就是說當串連池中沒有active/idle的串連時,會等待maxWait時間,如果等待逾時還沒有可用串連,則拋出Could not get a resource from the pool異常。所以為避免這樣的錯誤,

我們應該根據程式實際情況合理設定這三個參數的值,同時在我們擷取一個串連的程式方法中也應該合理的處理這個異常,當沒有串連可用時,等待一段時間再擷取也許是個比較好的選擇。


二、當我們擷取串連後對redis進行操作時,拋出redis.clients.jedis.exceptions.JedisConnectionException: java.net.SocketTimeoutException: Read timed out異常。

異常代碼如下:

redis.clients.jedis.exceptions.JedisConnectionException: java.net.SocketTimeoutException: Read timed out

at redis.clients.jedis.Protocol.process(Protocol.java:79)
at redis.clients.jedis.Protocol.read(Protocol.java:131)
at redis.clients.jedis.Connection.getIntegerReply(Connection.java:188)
at redis.clients.jedis.Jedis.sismember(Jedis.java:1266)
這是一個比較麻煩的異常,困擾了我一天的時間。我們都知道Redis是對記憶體進行操作,速度應該都在毫秒級,這是我們通常的認識,所以當對Redis操作出現幾秒的逾時時間,你能想象嗎。
我們還是先分析一下Jedis的原始碼吧,以sadd操作為例:
public Long sadd(final String key, final String... members) { checkIsInMulti(); client.sadd(key, members); return client.getIntegerReply(); } client是redis.clients.jedis.Client.java的執行個體,繼承關係如下:
public class Client extends BinaryClient implements Commands;

public class BinaryClient extends Connection; Connection封裝了對Redis server的socket操作,命令寫操作通過socket.getOutputStream()輸出資料流將命令資訊發送到redis server,當寫完命令後要通過socket.getInputStream()的到的輸入資料流將
命令執行結果返回,這中間必然會有一個命令執行到結果返回的延時時間,這就是一個Jedis調用redis命令操作所用的時間。

需要說明的是,Redis server是單線程執行所有串連發送過來的命令的,也就是說不管並發中有多少個client在發送命令,redis-server端是單線程處理的,並按照預設的FIFO方式處理請求,

這個可在redis.conf設定檔中配置。關於redis server的詳細運行機制參見:http://redis.io/documentation 所以client.sadd(key, members);調用完後只是將命令資訊發送到了redis server端,具體有沒有執行要看redis server的負載情況。然後,通過client.getIntegerReply();等待(time out)返回結果。
Connection初始化socket時有多種選擇,其中設定socket time out 的方法如下:
public void rollbackTimeout() {           try {             socket.setSoTimeout(timeout);             socket.setKeepAlive(false);           } catch (SocketException ex) {             throw new JedisException(ex);           }       } 由redis.clients.jedis.Protocol.DEFAULT_TIMEOUT = 2000 我們知道預設的逾時時間是2秒,這個時間相對於redis操作記憶體毫秒級的速度來說已經很長,那我們為什麼還會遇到
ava.net.SocketTimeoutException: Read timed out異常呢。redis操作記憶體雖然平均毫秒級的,但當資料量很大時未必都如此快速。在我的開發過程中就遇到過一個集合到了

千萬級資料量,一次操作逾時時間在秒級是很正常的,而且機器效能很好的情況下已經如此,更何況我們本機開發的機器相對於生產伺服器來說速度會更慢了。所以在初始化JedisPool時應該根據實際

情況通過redis.clients.jedis.JedisPoolConfig合理設定串連池參數,通過edisPool構造方法,合理設定socket讀取輸入InputStream的逾時時間。

pool = new JedisPool(config, host, port, 100000);

注意第四個參數time out,設定成我們能容忍的逾時時間,單位是毫秒。但不知道為什麼既然單位是毫秒,為什麼參數類型是int而不是long。

設定第四個參數後,我在四千萬資料量集合上操作最多一次大概逾時5秒,問題基本解決。

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.