【redis】客户端场景异常

1.无法从连接池获取到连接

JedisPool中的Jedis对象个数是有限的,默认是8个。这里假设使用的默认配置,
如果有8个Jedis对象被占用,并且没有归还,此时调用者还要从JedisPool中借用
Jedis,就需要进行等待(例如设置了 maxWaitMillis>0),如果在maxWaitMillis时间
内仍然无法获取到Jedis对象就会抛出异常:

redis.clients.jedis.exception.JedisConnectionException:Could not get a 
resource from the pool 
Caused by :java.util.NoSuchElementException:Timeout waiting for idle object
 at org.apache.commons.pool2.impl.GenericObjectPool.borrowObject(GenericObjectPool)

还有一种情况是设置了blockWhenExhausted=false,那么调用者发现池子没有资源时,
会立即抛出异常不进行等待。
redis.clients.jedis.exception.JedisConnectionException:Could not get a 
resource from the pool 
...
caused by :java.util.NoSuchElementException:Pool exhausted 
 at org.apache.commons.pool2.impl.GenericObjectPool.borrowObject(GenericObjectPool)

造成连接池么有资源的原因如下。
客户端:
高并发下连接池设置过小,出现供不应求,所以会出现上面的错误。但是正常情况
下只要比默认的最大连接数8多一些即可。因为正常JedisPool以及redis的处理效率
足够高。
客户端:没有正确使用连接池,比如没有进行释放。
客户端:存在慢查询操作,这些慢查询持有的Jedis对象归还速度比较慢,造成池子满了。
服务端:客户端是正常的,但是redis服务端由于一些原因造成了客户端命令执行过程的阻塞,
也会使得客户端抛出异常。

2.客户端读写超时。

Jedis 在调用Redis时,如果出现了读写超时后,会出现下面的异常:
redis.clients.jedis.exception.JedisConnectionException:
java.net.SocketTimeoutException:Read timed out 

造成原因有如下几种:
读写超时时间设置得过短 
命令本身就比较慢。
客户端和服务端网络不正常 
redis自身发送阻塞。

3.客户端连接超时 

Jedis在调用redis时,出现连接超时会出现下面的异常:
redis.clients.jedis.exception.JedisConnectionException:
java.net.SocketTimeoutException:connect timed out 

原因有几下几种:
连接超时设置得过短,可以通过下面代码设置。
jedis.getClient().setConnectionTimeout(time)
redis发生阻塞,造成tcp-backlog已满,造成新的连接失败。
客户端与服务端网络不正常。

4.客户端缓冲区异常

Jedis在调用redis时,如果出现客户端数据流异常:
redis.clients.jedis.exception.JedisConnectionException:
Unexpected end of stream;

原因有如下几种:
输出缓冲区满。例如将普通客户端的输出缓冲区设置为:1M 1M 60 
config set client-output-buffer-limit "normal 1048576 1048576 60"
此时使用get命令设置一个bigKey(3M)就会出现异常。
长时间闲置连接被服务端主动断开。
不正常并发读写:Jedis对象同时被多个线程并发操作。

5.Lua脚本正在执行

如果redis当前正在执行lua脚本,并且超过了lua-time-limit,
此时Jedis调用Redis时,会收到下面的异常:
redis.clients.jedis.exception.JedisDataException:BUSY Redis is 
busy running a script.You can only call SCRIPT KILL or SHUDOWN NOSAVE; 

6.redis正在加载持久化文件

Jedis调用redis时,如果redis正在加载持久化文件,那么会收到如下:
redis.clients.jedis.exception.JedisDataException:LOADING Redis is 
loading the dataset in memory; 

7.Redis使用的内存超过maxmemory配置

Jedis执行写操作时,如果redis的使用内存大于maxmemory的设置,会有如下报错:
此时需要调整maxmemory并找到造成增长的原因。
redis.clients.jedis.exception.JedisDataException:OOM command not allowed 
when used memory>'maxmemory'

8.客户端连接数过大 

如果客户端连接数过大超过了maxclient,新申请的连接出现异常:
redis.clients.exception.JedisDataException:ERR max number of clients 
reached 
此时任何命令都返回:
(error) ERR max number of clients reached

此时可以从两个方面着手:
客户端: 
如果maxclients参数不是很小的话,应用方的客户端连接数基本不会超过maxclients,
通常来看是由于应用方对于Redis的客户端使用不当造成的。此时如果应用方是分布式
结构的话,可以通过下线部分应用节点,使得redis的连接数先降下来。让绝大部分
的节点可以正常使用,在修复问题。

服务端: 
如果此时客户端无法处理,而当前redis为高可用模式(redis sentinel和rediscluster)
可以考虑当前redis做故障转移。
此问题不存在确定的解决方式,故障的快速修复最重要。然后找到问题的原因。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值