`
ssxxjjii
  • 浏览: 938670 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

常见JedisConnectionException异常分析

 
阅读更多

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操作为例:

  1. public Long sadd(final String key, final String... members) {
  2. checkIsInMulti();
  3. client.sadd(key, members);
  4. return client.getIntegerReply();
  5. }

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 的方法如下:

  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.      }

由redis.clients.jedis.Protocol.DEFAULT_TIMEOUT = 2000 我们知道默认的超时时间是2秒,这个时间相对于redis操作内存毫秒级的速度来说已经很长,那我们为什么还会遇到
ava.net.SocketTimeoutException: Read timed out异常呢?redis操作内存虽然平均毫秒级的,但当数据量很大时未必都如此快速。在我的开发过程中就遇到过一个集合到了

千万级数据量,一次操作超时时间在秒级是很正常的,而且机器性能很好的情况下已经如此,更何况我们本机开发的机器相对于生产服务器来说速度会更慢了。所以在初始化JedisPool时应该根据实际

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

 

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

 

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

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

分享到:
评论
1 楼 yangkf1985 2014-04-14  
lz辛苦了,我想问您第一个问题,
1、JedisPoolConfig的那三个参数,该设置一个怎么样的值,才是最合适或者说推荐值;
2、SharedJedis如何才能彻底的释放链接,我使用sharedJedisPool.returnResourceObject();
3、我现在的情况是20个Tomcat,同时请求。JedisPool的配置:{MaxActive=500,MaxIdle=100,MaxWait=2000}
Redis的Maxclients=655328。当大量并发请求出现时,就会报错:redis.clients.jedis.exceptions.JedisConnectionException: Could not get a resource from the pool

at redis.clients.util.Pool.getResource(Pool.java:22)
希望LZ帮忙,谢谢!

相关推荐

    Redis常见客户端异常.docx

    本文将详细介绍 Redis 客户端常见的异常类型、原因和解决方法。 一、无法从连接池获取连接异常 在使用 JedisPool 连接 Redis 时,可能会出现无法从连接池获取连接的异常。这是因为 JedisPool 中的 Jedis 对象个数...

    Redis连接超时异常的处理方法

    Exception in thread “main” redis.clients.jedis.exceptions.JedisConnectionException: java.net.SocketTimeoutException: Read timed out  at redis.clients.util.RedisInputStream.ensureFill...

    redis linux系统安装和操作

    在使用 Redis 时,可能会遇到连接异常,例如 JedisConnectionException。解决连接异常的方法包括: * 检查地址或端口是否正确 * 检查防火墙是否开放 6379 端口 * 检查 Redis 服务是否正常运行 通过以上知识点,...

    jedis-jedis-2.8.2.zip

    Jedis库封装了常见的Redis操作异常,如`JedisConnectionException`、`JedisDataException`等,帮助开发者更好地处理错误和异常情况。 总的来说,Jedis 2.8.2作为一款强大的Redis客户端,提供了全面的Redis命令接口...

    jedis-jedis-3.4.1.tar.gz

    - Jedis库中有各种特定的异常,如`JedisConnectionException`表示连接问题,`JedisDataException`表示数据操作异常等。在编写代码时,需要适当地捕获这些异常以处理错误情况。 7. **配置优化**: - 用户可以通过...

    jedis-jedis-3.1.0-m1.tar.gz

    6. **异常处理**:Jedis提供了丰富的异常类,如`JedisConnectionException`、`JedisDataException`等,帮助开发者识别和处理可能出现的问题。 7. **配置与升级**:Jedis的配置可以通过Java代码或属性文件完成,例如...

    Jedis源码-供查询redis API源码

    5. **Exception Handling** - Jedis封装了与Redis通信可能出现的异常,如`JedisDataException`、`JedisConnectionException`等,方便开发者捕获和处理错误。 ### 源码分析 在源码中,我们可以看到Jedis是如何实现...

    详解Redis开启远程登录连接

    redis.clients.jedis.exceptions.JedisConnectionException: java.net.ConnectException: Connection refused: connect at redis.clients.jedis.Connection.connect(Connection.java:164) at redis.clients.jedis....

    jedis 2.1源码

    7. **异常处理**:Jedis在遇到网络问题、命令执行错误等情况时,会抛出相应的异常,如`JedisConnectionException`、`JedisDataException`等。理解这些异常的产生条件和处理方式,有助于编写健壮的代码。 8. **持久...

    Jedis-2.7.2

    10. **错误处理和异常**:Jedis库抛出了一系列自定义的异常,如`JedisConnectionException`表示网络连接问题,`JedisDataException`表示Redis数据操作异常,便于开发者进行异常处理和调试。 在实际开发中,为了更好...

    jedis源码 (学习jedis)

    源码中包含了各种异常类,如`JedisConnectionException`、`JedisDataException`等,它们对应Redis操作可能遇到的问题。通过异常处理,可以更好地理解和调试程序。 通过学习Jedis的源码,不仅能掌握Jedis的使用,还...

    jedis-3.6.2.tar.gz

    7. **错误处理和异常机制**:Jedis 抛出的异常通常可以帮助开发者快速定位问题,例如 RedisException、JedisConnectionException 等。正确处理这些异常是保证应用稳定运行的关键。 8. **版本更新**:从 Jedis 3.6.2...

    jedisRedis的Java客户端

    - Jedis操作过程中可能会遇到各种异常,如`JedisConnectionException`表示连接问题,`RedisException`是通用的Redis异常。应合理捕获并处理这些异常,确保程序的健壮性。 9. **版本更新与兼容性** - 不断更新的...

    jedis-jedis-2.10.0-m1.tar.gz

    9. **异常处理**:Jedis通过抛出不同类型的异常,如JedisConnectionException、JedisDataException等,帮助开发者识别和处理各种运行时问题。 10. **测试与示例**:Jedis项目包含了大量的单元测试,覆盖了各种功能...

    jedis-jedis-3.4.0.zip

    - Jedis封装了多种与Redis交互可能出现的异常,如`JedisConnectionException`表示连接问题,`JedisDataException`表示数据操作错误等。开发人员需要根据这些异常进行适当的错误处理。 8. **配置优化**: - 用户...

    jedis-jedis-2.9.2.tar.gz

    8. **异常处理**:Jedis会抛出各种异常,如`JedisConnectionException`表示连接问题,`JedisDataException`表示数据操作错误,需要适当地捕获和处理这些异常。 9. **最佳实践**:使用Jedis时应注意连接池配置,合理...

    jedis-2.1.0-sources.jar

    8. **异常处理**:Jedis抛出一系列与Redis操作相关的异常,如`JedisConnectionException`、`JedisDataException`等,帮助开发者快速定位和处理错误。 9. **异步API**:虽然Jedis主要是同步操作,但在Jedis 3.x版本...

    jedis2.9-common-pool

    5. **异常处理**:在使用Jedis时,需要捕获并处理可能出现的异常,如`JedisConnectionException`等,以保证程序的健壮性。 通过以上方式,我们可以充分利用Jedis 2.9的功能,同时借助Apache Commons Pool进行高效的...

    jedis-jedis-2.9.2.zip

    8. **异常处理**:Jedis会抛出一系列的异常,如`JedisConnectionException`、`JedisDataException`等,帮助开发者快速定位和处理问题。 9. **性能优化**:Jedis通过缓存结果、重用连接和命令对象等方式进行了性能...

    jedis-2.7.2(jar包)

    6. **异常处理**:Jedis在执行操作时可能会抛出异常,如`JedisConnectionException`、`JedisDataException`等,需要适当地捕获并处理这些异常。 7. **Jedis 2.7.2的改进**:这个版本修复了一些已知的bug,提升了...

Global site tag (gtag.js) - Google Analytics