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 是为了处理应用程序的异常行为而 ...
随机推荐
- quartz的一个误导
quartz文档提到,如果在集群环境下,最好将配置项org.quartz.jobStore.txIsolationLevelSerializable设置为true 问题: 这个选项在mysql下会非常 ...
- FM的推导原理--推荐系统
FM:解决稀疏数据下的特征组合问题 Factorization Machine(因子分解机) 美团技术团队的文章,觉得写得很好啊:https://tech.meituan.com/deep-unde ...
- thinkphp模型创建
- 通过field:global给子元素添加css样式
{dede:arclist row=5 typeid=200} <li [field:global runphp=’yes’ name=autoindex](@me==1)?@me=”class ...
- Java 容器的基本概念
java容器类类库的用途时"保存对象",并将其划分为两个不同的概念: 1)Collection(采集).一个独立元素的序列,这些元素都服从一条或多条规则,List必须按照插入的顺序 ...
- 【[国家集训队]小Z的袜子】
对于L,R的询问.设其中颜色为x,y,z的袜子的个数为a,b,c...那么答案即为(a*(a-1)/2+b*(b-1)/2+c*(c-1)/2....)/((R-L+1)*(R-L)/2)化简得:(a ...
- qlserver排序规则在全角与半角处理中的应用
--1.查询区分全角与半角字符--测试数据DECLARE @t TABLE(col varchar(10))INSERT @t SELECT 'aa'UNION ALL SELECT 'Aa'UNIO ...
- 专业分析docker的分层存储技术
话不在多,指明要点! 联合挂载是用于将多个镜像层的文件系统挂载到一个挂载点来实现一个统一文件系统视图的途径, 是下层存储驱动(aufs.overlay等) 实现分层合并的方式. 所以严格来说,联合挂载 ...
- CCF CSP 201703-4 地铁修建
博客中的文章均为meelo原创,请务必以链接形式注明本文地址 CCF CSP 201703-4 地铁修建 问题描述 A市有n个交通枢纽,其中1号和n号非常重要,为了加强运输能力,A市决定在1号到n ...
- 【LOJ】#2063. 「HAOI2016」字符合并
题解 dp[i][j][S]表示区间[i,j]内剩余的数位状压后为S的最大值 这样转移起来不就是\(n^3 2^8\)了吗 冷静一下,我们可以发现一段区间内剩下的数位的个数是一定的,也就是我们可以在枚 ...