http://blog.csdn.net/fachang/article/details/7984123 Analysis of common JedisConnectionException exceptions

http://blog.csdn.net/fachang/article/details/7984123


Common JedisConnectionException analysis

original  September 16, 2012 15:09:48
Recently, Redis was used in project development, and the java client Jedis recommended by the official website was selected.
Redis common command learning: http://redis.io/commands
Redis officially recommends Java client Jedis (including the implementation of all Redis commands): https://github.com/xetorthio/jedis

The most common exception in the use of Jedis is JedisConnectionException Sometimes it does bring us a lot of confusion, this exception usually occurs in two scenarios.

1. When we execute the getResource() of the following JedisPool class instance, a can't get a resource exception is thrown.

The exception code is as follows:

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

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

analyze:

redis.clients.util.Pool.getResource will return an available redis connection from the pool of JedisPool instances. Analysis of the source code shows that JedisPool extends redis.clients.util.Pool<Jedis>  . And Pool<T> is passed through

The org.apache.commons.pool.impl.GenericObjectPool in the commons-pool open source toolkit is used to manage Jedis instances. So we may find the answer by analyzing GenericObjectPool.

First take a look at the common-pool api: http://commons.apache.org/pool/apidocs/index.html?org/apache/commons/pool/impl/GenericObjectPool.html .
Three of the important properties are:
MaxActive : The maximum number of available connection instances, no limit when negative.
MaxIdle : The maximum number of idle connection instances, there is no limit when it is negative. An instance of Idle is usually made available via the activateObject() method of org.apache.commons.pool.BasePoolableObjectFactory<T> before it can be used.
MaxWait : The maximum number of connections to wait for available, in milliseconds (million seconds).
     (Note: The borrowObject() method of the GenericObjectPool class actually called by the pool.getResource() method will block and wait until there is no available connection (idle/active) according to the value of the MaxWait variable. Please refer to the api for the specific meaning.)

That is to say, when there is no active/idle connection in the connection pool, it will wait for the maxWait time. If there is no available connection after the timeout, the Could not get a resource from the pool exception will be thrown. So to avoid such mistakes,

We should reasonably set the values ​​of these three parameters according to the actual situation of the program . At the same time, we should also handle this exception reasonably in the program method of obtaining a connection. When no connection is available, it may be a better choice to wait for a while before obtaining it. .


2. When we operate redis after obtaining the connection, redis.clients.jedis.exceptions.JedisConnectionException: java.net.SocketTimeoutException: Read timed out exception is thrown.

The exception code is as follows:

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)

This is one of the more troublesome exceptions that haunts me for the time of day. We all know that Redis operates on memory, and the speed should be in milliseconds. This is our usual understanding, so when there is a timeout of several seconds for Redis operations, can you imagine it?
Let's analyze the source code of Jedis first, taking the sadd operation as an example:
  1. public Long sadd(final String key, final String... members) {
  2. checkIsInMulti();
  3. client.sadd(key, members);
  4. return client.getIntegerReply();
  5. }
client is an instance of redis.clients.jedis.Client.java, and the inheritance relationship is as follows:
public class Client extends BinaryClient implements Commands;

public class BinaryClient extends Connection;

Connection wraps the socket operation on the Redis server. The command write operation sends the command information to the redis server through the socket.getOutputStream() output stream. After the command is written, the
command execution result is sent through the incoming input stream of socket.getInputStream(). Return, there must be a delay time between command execution and result return, which is the time it takes for a Jedis to call a redis command operation.

It should be noted that the Redis server executes all commands sent by the connection in a single thread, that is to say, no matter how many clients are sending commands concurrently, the redis-server side is processed in a single thread and is processed in the default FIFO mode. ask,

This can be configured in the redis.conf configuration file . For the detailed operation mechanism of redis server, see: http://redis.io/documentation

So client.sadd(key, members); just sends the command information to the redis server after the call is completed. Whether it is executed depends on the load of the redis server. Then, through client.getIntegerReply(); wait (time out) to return the result.
Connection has a variety of options when initializing the socket. The method of setting the socket time out is as follows:
  1. public void rollbackTimeout() {
  2.           try {
  3.             socket.setSoTimeout(timeout);
  4.             socket.setKeepAlive(false);
  5.           } catch (SocketException ex) {
  6.             throw new JedisException(ex);
  7.           }
  8.       }
From redis.clients.jedis.Protocol.DEFAULT_TIMEOUT = 2000, we know that the default timeout is 2 seconds, which is already very long compared to the millisecond speed of redis operation memory, so why do we still encounter
ava.net. SocketTimeoutException: Read timed out exception? Although redis operates on the average millisecond level, it may not be so fast when the amount of data is large. In my development process, I encountered a collection to

With a data volume of tens of millions, it is normal for an operation to have a timeout in seconds, and this is already the case when the machine performance is very good, not to mention that the machine we developed locally will be slower than the production server. So when initializing the JedisPool, it should be based on the actual

情况通过redis.clients.jedis.JedisPoolConfig合理设置连接池参数,通过edisPool构造方法,合理设置socket读取输入InputStream的超时时间。

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

注意第四个参数time out,设置成我们能容忍的超时时间,单位是毫秒。但不知道为什么既然单位是毫秒,为什么参数类型是int而不是long。

设置第四个参数后,我在四千万数据量集合上操作最多一次大概超时5秒,问题基本解决。

最近项目开发中用到了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)

This is one of the more troublesome exceptions that haunts me for the time of day. We all know that Redis operates on memory, and the speed should be in milliseconds. This is our usual understanding, so when there is a timeout of several seconds for Redis operations, can you imagine it?
Let's analyze the source code of Jedis first, taking the sadd operation as an example:
  1. public Long sadd(final String key, final String... members) {
  2. checkIsInMulti();
  3. client.sadd(key, members);
  4. return client.getIntegerReply();
  5. }
client is an instance of redis.clients.jedis.Client.java, and the inheritance relationship is as follows:
public class Client extends BinaryClient implements Commands;

public class BinaryClient extends Connection;

Connection wraps the socket operation on the Redis server. The command write operation sends the command information to the redis server through the socket.getOutputStream() output stream. After the command is written, the
command execution result is sent through the incoming input stream of socket.getInputStream(). Return, there must be a delay time between command execution and result return, which is the time it takes for a Jedis to call a redis command operation.

It should be noted that the Redis server executes all commands sent by the connection in a single thread, that is to say, no matter how many clients are sending commands concurrently, the redis-server side is processed in a single thread and is processed in the default FIFO mode. ask,

This can be configured in the redis.conf configuration file . For the detailed operation mechanism of redis server, see: http://redis.io/documentation

So client.sadd(key, members); just sends the command information to the redis server after the call is completed. Whether it is executed depends on the load of the redis server. Then, through client.getIntegerReply(); wait (time out) to return the result.
Connection has a variety of options when initializing the socket. The method of setting the socket time out is as follows:
  1. public void rollbackTimeout() {
  2.           try {
  3.             socket.setSoTimeout(timeout);
  4.             socket.setKeepAlive(false);
  5.           } catch (SocketException ex) {
  6.             throw new JedisException(ex);
  7.           }
  8.       }
From redis.clients.jedis.Protocol.DEFAULT_TIMEOUT = 2000, we know that the default timeout is 2 seconds, which is already very long compared to the millisecond speed of redis operation memory, so why do we still encounter
ava.net. SocketTimeoutException: Read timed out exception? Although redis operates on the average millisecond level, it may not be so fast when the amount of data is large. In my development process, I encountered a collection to

With a data volume of tens of millions, it is normal for an operation to have a timeout in seconds, and this is already the case when the machine performance is very good, not to mention that the machine we developed locally will be slower than the production server. So when initializing the JedisPool, it should be based on the actual

In the case, the connection pool parameters are set reasonably through redis.clients.jedis.JedisPoolConfig, and the timeout time for socket reading the input InputStream is set reasonably through the edisPool construction method.

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

注意第四个参数time out,设置成我们能容忍的超时时间,单位是毫秒。但不知道为什么既然单位是毫秒,为什么参数类型是int而不是long。

设置第四个参数后,我在四千万数据量集合上操作最多一次大概超时5秒,问题基本解决。

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=325949208&siteId=291194637