当前位置:网站首页>Redis入门完整教程:客户端常见异常
Redis入门完整教程:客户端常见异常
2022-07-06 19:11:00 【谷哥学术】
在客户端的使用过程中,无论是客户端使用不当还是Redis服务端出现
问题,客户端会反应出一些异常。本小节将分析一下Jedis使用过程中常见
的异常情况。
1.无法从连接池获取到连接
JedisPool中的Jedis对象个数是有限的,默认是8个。这里假设使用的默
认配置,如果有8个Jedis对象被占用,并且没有归还,此时调用者还要从
JedisPool中借用Jedis,就需要进行等待(例如设置了maxWaitMillis>0),如
果在maxWaitMillis时间内仍然无法获取到Jedis对象就会抛出如下异常:
redis.clients.jedis.exceptions.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.
java:449)
还有一种情况,就是设置了blockWhenExhausted=false,那么调用者发现
池子中没有资源时,会立即抛出异常不进行等待,下面的异常就是
blockWhenExhausted=false时的效果:
redis.clients.jedis.exceptions.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.
java:464)
对于这个问题,需要重点讨论的是为什么连接池没有资源了,造成没有
资源的原因非常多,可能如下:
·客户端:高并发下连接池设置过小,出现供不应求,所以会出现上面
的错误,但是正常情况下只要比默认的最大连接数(8个)多一些即可,因
为正常情况下JedisPool以及Jedis的处理效率足够高。
·客户端:没有正确使用连接池,比如没有进行释放,例如下面代码所
示。
定义JedisPool,使用默认的连接池配置:
GenericObjectPoolConfig poolConfig = new GenericObjectPoolConfig();
JedisPool jedisPool = new JedisPool(poolConfig, "127.0.0.1", 6379);
像JedisPool借用8次连接,但是没有执行归还操作:
for (int i = 0; i < 8; i++) {
Jedis jedis = null;
try {
jedis = jedisPool.getResource();
jedis.ping();
} catch (Exception e) {
e.printStackTrace();
}
}
当调用者再向连接池借用Jedis时(如下操作),就会抛出异常:
jedisPool.getResource().ping();
·客户端:存在慢查询操作,这些慢查询持有的Jedis对象归还速度会比
较慢,造成池子满了。
·服务端:客户端是正常的,但是Redis服务端由于一些原因造成了客户
端命令执行过程的阻塞,也会使得客户端抛出这种异常。
可以看到造成这个异常的原因是多个方面的,不要被异常的表象所迷
惑,而且并不存在万能钥匙解决所有问题,开发和运维只能不断加强对于
Redis的理解,顺藤摸瓜逐渐找到问题所在。
2.客户端读写超时
Jedis在调用Redis时,如果出现了读写超时后,会出现下面的异常:
redis.clients.jedis.exceptions.JedisConnectionException:
java.net.SocketTimeoutException: Read timed out
造成该异常的原因也有以下几种:
·读写超时间设置得过短。
·命令本身就比较慢。
·客户端与服务端网络不正常。
·Redis自身发生阻塞。
3.客户端连接超时
Jedis在调用Redis时,如果出现了连接超时后,会出现下面的异常:
redis.clients.jedis.exceptions.JedisConnectionException:
java.net.SocketTimeoutException: connect timed out
造成该异常的原因也有以下几种:
1)连接超时设置得过短,可以通过下面代码进行设置:
// 毫秒
jedis.getClient().setConnectionTimeout(time);
2)Redis发生阻塞,造成tcp-backlog已满,造成新的连接失败。
3)客户端与服务端网络不正常。
4.客户端缓冲区异常
Jedis在调用Redis时,如果出现客户端数据流异常,会出现下面的异
常:
redis.clients.jedis.exceptions.JedisConnectionException: Unexpected end of stream.
造成这个异常的原因可能有如下几种:
1)输出缓冲区满。例如将普通客户端的输出缓冲区设置为1M1M60:
config set client-output-buffer-limit "normal 1048576 1048576 60 slave 268435456
67108864 60 pubsub 33554432 8388608 60"
如果使用get命令获取一个bigkey(例如3M),就会出现这个异常。
2)长时间闲置连接被服务端主动断开,上节已经详细分析了这个问
题。
3)不正常并发读写:Jedis对象同时被多个线程并发操作,可能会出现
上述异常。
5.Lua脚本正在执行
如果Redis当前正在执行Lua脚本,并且超过了lua-time-limit,此时Jedis
调用Redis时,会收到下面的异常。对于如何处理这类问题,在第3章Lua的
小节已经进行了介绍,这里就不再赘述。
redis.clients.jedis.exceptions.JedisDataException: BUSY Redis is busy running a
script. You can only call SCRIPT KILL or SHUTDOWN NOSAVE.
6.Redis正在加载持久化文件
Jedis调用Redis时,如果Redis正在加载持久化文件,那么会收到下面的
异常:
redis.clients.jedis.exceptions.JedisDataException: LOADING Redis is loading the
dataset in memory
7.Redis使用的内存超过maxmemory配置
Jedis执行写操作时,如果Redis的使用内存大于maxmemory的设置,会
收到下面的异常,此时应该调整maxmemory并找到造成内存增长的原因:
redis.clients.jedis.exceptions.JedisDataException: OOM command not allowed when
used memory > 'maxmemory'.
8.客户端连接数过大
如果客户端连接数超过了maxclients,新申请的连接就会出现如下异
常:
redis.clients.jedis.exceptions.JedisDataException: ERR max number of clients reached
此时新的客户端连接执行任何命令,返回结果都是如下:
127.0.0.1:6379> get hello
(error) ERR max number of clients reached
这个问题可能会比较棘手,因为此时无法执行Redis命令进行问题修
复,一般来说可以从两个方面进行着手解决:
·客户端:如果maxclients参数不是很小的话,应用方的客户端连接数基
本不会超过maxclients,通常来看是由于应用方对于Redis客户端使用不当造
成的。此时如果应用方是分布式结构的话,可以通过下线部分应用节点(例
如占用连接较多的节点),使得Redis的连接数先降下来。从而让绝大部分
节点可以正常运行,此时再通过查找程序bug或者调整maxclients进行问题的
修复。
·服务端:如果此时客户端无法处理,而当前Redis为高可用模式(例如
Redis Sentinel和Redis Cluster),可以考虑将当前Redis做故障转移。
此问题不存在确定的解决方式,但是无论从哪个方面进行处理,故障的
快速恢复极为重要,当然更为重要的是找到问题的所在,否则一段时间后客
户端连接数依然会超过maxclients。
边栏推荐
- fasterxml ToStringSerializerBase报错
- 【森城市】GIS数据漫谈(二)
- Overall query process of PostgreSQL
- 数字滚动增加效果
- Qpushbutton- "function refinement"
- Leetcode:minimum_ depth_ of_ binary_ Tree solutions
- Untiy文本框的代码换行问题
- A new path for enterprise mid Platform Construction -- low code platform
- 6-6 vulnerability exploitation SSH security defense
- HAVE FUN | “飞船计划”活动最新进展
猜你喜欢
Matlb| economic scheduling with energy storage, opportunity constraints and robust optimization
运维管理系统有哪些特色
MES管理系统的应用和好处有哪些
Google Earth Engine(GEE)——Landsat 全球土地调查 1975年数据集
Electrical engineering and automation
普通测试年薪15w,测试开发年薪30w+,二者差距在哪?
服装企业部署MES管理系统的五个原因
HAVE FUN | “飞船计划”活动最新进展
3--新唐nuc980 kernel支持jffs2, Jffs2文件系统制作, 内核挂载jffs2, uboot网口设置,uboot支持tftp
Linear list --- circular linked list
随机推荐
所谓的消费互联网仅仅只是做行业信息的撮合和对接,并不改变产业本身
【Socket】①Socket技术概述
Real project, realized by wechat applet opening code (end)
MySQL
实施MES管理系统时,哪些管理点是需要注意的
leetcode:736. LISP syntax parsing [flowery + stack + status enumaotu + slots]
3 -- Xintang nuc980 kernel supports JFFS2, JFFS2 file system production, kernel mount JFFS2, uboot network port settings, and uboot supports TFTP
Application analysis of face recognition
哈希表及完整注释
CSDN 夏令营课程 项目分析
一本揭秘字节万台节点ClickHouse背后技术实现的白皮书来了!
电气工程及其自动化
dotConnect for DB2数据提供者
导数、偏导数、方向导数
Halcon instance to opencvsharp (C openCV) implementation -- bottle mouth defect detection (with source code)
Remember the problem analysis of oom caused by a Jap query
Huitong programming introductory course - 2A breakthrough
Summer Challenge database Xueba notes (Part 2)~
[xlua notes] array of lua to array of C #
What management points should be paid attention to when implementing MES management system