Redis_常见JedisConnectionException异常分析
最近项目开发中用到了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秒,问题基本解决。
Redis_常见JedisConnectionException异常分析的更多相关文章
- 常见JedisConnectionException异常分析
异常内容:我看了很多人的博客,千篇一律都是说redis.conf文件的配置问题,发现并不能解决我的问题,今天写这个博客讲解一下我的解决办法: 遇到这个问题第一步:查看虚拟机的防火墙是否关闭,测试方法就 ...
- Android异常分析(转)
关于异常 异常? 异常就是一种程序中没有预料到的问题,既然是没有预料到的,就可能不在原有逻辑处理范围内,脱离了代码控制,软件可能会出现各种奇怪的现象.比如:android系统常见异常现象有应用无响应. ...
- 常见 Java 异常解释(恶搞版)
常见 Java 异常解释:(译者注:非技术角度分析.阅读有风险,理解需谨慎o(╯□╰)o) java.lang ArithmeticException 你正在试图使用电脑解决一个自己解决不了的数学问题 ...
- (转)Db2 数据库常见堵塞问题分析和处理
原文:https://www.ibm.com/developerworks/cn/analytics/library/ba-lo-db2-common-blocking-problem-analyze ...
- java.lang.ArrayIndexOutOfBoundsException异常分析及解决
这是一个非常常见的异常,从名字上看是数组下标越界错误,解决方法就是查看为什么下标越界. 下面是一个错误示例: Exception in thread "main" java.lan ...
- 【译】常见 Java 异常解释(恶搞版)
常见 Java 异常解释:(译者注:非技术角度分析.阅读有风险,理解需谨慎o(╯□╰)o) java.lang ArithmeticException 你正在试图使用电脑解决一个自己解决不了的数学问题 ...
- java中常见的异常种类
Java常见的异常种类 ------------------------------------------------------------------------------- java Exc ...
- java.lang.ArrayIndexOutOfBoundsException 异常分析及解决
参考:http://blog.csdn.net/javaeeteacher/article/details/4485834 这是一个非常常见的异常,从名字上看是数组下标越界错误,解决方法就是查看为什么 ...
- Java 异常分析
Java 异常分析 本文是对以下内容的分析: Java异常设计 Java 异常分类 Java异常可以告诉什么问题 Java异常处理最佳实践 Java Exception 是为了处理应用程序的异常行为而 ...
随机推荐
- DevExpress GridControl 的数据绑定
本人不才啊,折腾2个多小时才把数据绑定好.现在把折腾过程记录一下来以帮助更多的朋友,自己也温习一下. 直接上代码了哈.... WPF哈 xaml文件 <dxg:GridControl Name= ...
- 虚拟机 CentOS7 64
下载地址:https://www.centos.org/download/ 下载完后以后使用虚拟机安装即可
- Codeforces 801C Voltage Keepsake(二分枚举+浮点(模板))
题目链接:http://codeforces.com/contest/801/problem/C 题目大意:给你一些电器以及他们的功率,还有一个功率一定的充电器可以给这些电器中的任意一个充电,并且不计 ...
- Python学习笔记:个税起征点上调至5000,算一算少交多少税?
一.旧税率表与新税率表比较 以前起征点是3500,2018年10月1日起起征点正式修改为5000,下面我们用Python来分别计算新旧个人所得税分别为多少? 二.旧的个人所得税 import sys ...
- Zabbix监控websphere和weblogic
本节内容 zabbix java gateway 配置和运行java gateway 配置zabbix server使用java gateway 调整java gateway的日志级别 监控weblo ...
- CCF CSP 201709-1 打酱油
CCF计算机职业资格认证考试题解系列文章为meelo原创,请务必以链接形式注明本文地址 CCF CSP 201709-1 打酱油 问题描述 小明带着N元钱去买酱油.酱油10块钱一瓶,商家进行促销,每买 ...
- Hive(四)Hive的3种连接方式与DbVisualizer连接Hive
一.CLI连接 进入到 bin 目录下,直接输入命令: [root@node21 ~]# hive SLF4J: Class path contains multiple SLF4J bindings ...
- Java访问者模式
结构对象会遍历它自己所保存的聚集中的所有节点,在本系统中就是节点NodeA和NodeB.首先NodeA会被访问到,这个访问是由以下的操作组成的: (1)NodeA对象的接受方法accept()被调用, ...
- git推送本地仓库到github
总结一下,方便后人,也方便自己查阅.直接写步骤 一.本地创建一个文件夹,在里面写项目的文件(* .php/*.js.....). git本地操作: 1 . cd /path/to/project ...
- Cygwin镜像使用
前言:Cygwin是一个在windows平台上运行的类UNIX模拟环境,可以自己安装想用的插件 Cygwin镜像使用帮助 收录架构 x86 x86_64 收录版本 所有版本 更新时间 每12小时更新一 ...