Rumah > pangkalan data > Redis > teks badan

Jedis使用中常见的客户端异常情况(汇总)

青灯夜游
Lepaskan: 2021-05-31 17:13:10
ke hadapan
2872 orang telah melayarinya

本篇文章给大家介绍一下Redis常见客户端异常汇总(Jedis篇)。有一定的参考价值,有需要的朋友可以参考一下,希望对大家有所帮助。

Jedis使用中常见的客户端异常情况(汇总)

【导读】Jedis是Redis的java版本的客户端实现。在Redis客户端的使用过程中,无论是客户端使用不当或者Redis服务端出现问题,客户端会反应出一些异常,本文分析了Jedis使用过程中常见的异常情况。【相关推荐:Redis视频教程

一、无法从连接池获取到连接

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)
Salin selepas log masuk

还有一种情况,就是设置了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)
Salin selepas log masuk

对于这个问题,需要重点讨论的是为什么连接池没有资源了,造成没有资源的可能的原因非常多

1.客户端:高并发下连接池设置过小,出现供不应求,所以会出现上面的错误,但是正常情况下只要比默认的最大连接数(8个)多一些即可,因为正常情况下JedisPool以及Jedis的处理效率足够高。

2.客户端:没有正确使用连接池,比如没有进行释放,例如下面代码所示:定义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();
    }
}
Salin selepas log masuk

当调用者再向连接池借用Jedis时(如下操作),就会抛出异常:

jedisPool.getResource().ping();

3.客户端:存在慢查询操作,这些慢查询持有的Jedis对象归还速度会比较慢,造成池子满了。

4.服务端:客户端是正常的,但是Redis服务端由于一些原因造成了客户端命令执行过程的阻塞,也会使得客户端抛出这种异常。可以看到造成这个异常的原因是多个方面的,不要被异常的表象所迷惑,而且并不存在万能钥匙能解决所有问题,开发和运维只能不断加强对于Redis的理解,顺藤摸瓜逐渐找到问题所在。

二、 客户端读写超时

Jedis在调用Redis时,如果出现了读写超时后,会出现下面的异常:

redis.clients.jedis.exceptions.JedisConnectionException: java.net.SocketTimeoutException: Read timed out
Salin selepas log masuk

造成该异常的原因也有以下几种:

读写超时设置的过短。
命令本身就比较慢。
客户端与服务端网络不正常。
Redis自身发生阻塞。

三、客户端连接超时

Jedis在调用Redis时,如果出现了读写超时后,会出现下面的异常:

redis.clients.jedis.exceptions.JedisConnectionException: java.net.SocketTimeoutException: connect timed out
Salin selepas log masuk

造成该异常的原因也有以下几种:

连接超时设置的过短。
Redis发生阻塞,造成tcp-backlog已满,造成新的连接失败。
客户端与服务端网络不正常。

四、客户端缓冲区异常

Jedis在调用Redis时,如果出现客户端数据流异常,会出现下面的异常。

redis.clients.jedis.exceptions.JedisConnectionException: Unexpected end of stream.
Salin selepas log masuk

造成这个异常原因可能有如下几种:

1.输出缓冲区满。例如将普通客户端的输出缓冲区设置为1M 1M 60:

config set client-output-buffer-limit "normal 1048576 1048576 60 slave 268435456 67108864 60 pubsub 33554432 8388608 60"
Salin selepas log masuk

如果使用get命令获取一个bigkey(例如3M),就会出现这个异常。

2.长时间闲置连接被服务端主动断开,可以查询timeout配置的设置以及自身连接池配置是否需要做空闲检测。

3.不正常并发读写:Jedis对象同时被多个线程并发操作,可能会出现上述异常。

五、Lua脚本正在执行

如果Redis当前正在执行Lua脚本,并且超过了lua-time-limit,此时Jedis调用Redis时,会收到下面的异常。对于如何处理这类问题(Lua lua-time-limit配置之前章节已经介绍了)

redis.clients.jedis.exceptions.JedisDataException: BUSY Redis is busy running a script. You can only call SCRIPT KILL or SHUTDOWN NOSAVE.
Salin selepas log masuk

六、Redis正在加载持久化文件

Jedis调用Redis时,如果Redis正在加载持久化文件,那么会收到下面的异常。

redis.clients.jedis.exceptions.JedisDataException: LOADING Redis is loading the dataset in memory
Salin selepas log masuk

七、Redis使用的内存超过maxmemory配置

Jedis调用Redis执行写操作时,如果Redis的使用内存大于maxmemory的设置,会收到下面的异常,此时应该调整maxmemory并找到造成内存增长的原因(maxmemory之前章节已经介绍了)

redis.clients.jedis.exceptions.JedisDataException: OOM command not allowed when used memory > &#39;maxmemory&#39;.
Salin selepas log masuk

八、客户端连接数过大

如果客户端连接数超过了maxclients,新申请的连接就会出现如下异常:

redis.clients.jedis.exceptions.JedisDataException: ERR max number of clients reached
Salin selepas log masuk

此时新的客户端连接执行任何命令,返回结果都是如下:

127.0.0.1:6379> get hello
(error) ERR max number of clients reached
Salin selepas log masuk

这个问题可能会比较棘手,因为此时无法执行Redis命令,一般来说可以从两个方面进行着手。

1.客户端:如果maxclients参数不是很小的话,应用方的客户端连接数基本不会超过maxclients,通常来看是由于应用方对于Redis客户端使用不当造成的。此时如果应用方是分布式结构的话,可以通过下线部分应用节点(例如占用连接较多的节点),使得Redis的连接数先降下来。从而让绝大部分节点可以正常运行,此时在再通过查找程序bug或者调整maxclients进行问题的修复。

2.服务端:如果此时客户端无法处理,而当前Redis为高可用模式(例如Redis Sentinel和Redis Cluster),可以考虑将当前Redis做故障转移。

此问题不存在确定的解决方式,但是无论从哪个方面进行处理,故障的快速恢复极为重要,当然更为重要的是找到问题的所在,否则一段时间后客户端连接数依然会超过maxclients。

附赠GenericObjectPoolConfig的重要属性

1.jpg

原文地址:https://mp.weixin.qq.com/s?__biz=MjM5NTk0MTM1Mw==&mid=2650650677&idx=1&sn=cbb1cb9fefdf9641a4a7c775660114e8&chksm=bef9c6b3898e4fa5a31ac6e572dca4c20a37d6c1dcb41004d831b34300c5c9ae0ed8c3a1bb45&scene=21#wechat_redirect

作者:付磊
Salin selepas log masuk

更多编程相关知识,请访问:编程教学!!

Atas ialah kandungan terperinci Jedis使用中常见的客户端异常情况(汇总). Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!

Label berkaitan:
sumber:segmentfault.com
Kenyataan Laman Web ini
Kandungan artikel ini disumbangkan secara sukarela oleh netizen, dan hak cipta adalah milik pengarang asal. Laman web ini tidak memikul tanggungjawab undang-undang yang sepadan. Jika anda menemui sebarang kandungan yang disyaki plagiarisme atau pelanggaran, sila hubungi admin@php.cn
Tutorial Popular
Lagi>
Muat turun terkini
Lagi>
kesan web
Kod sumber laman web
Bahan laman web
Templat hujung hadapan