当前位置: 首页 > news >正文

Redis学习(十二)连接数不足报错及分析修复:ERR max number of clients reached.

目录

    • 一、问题介绍
    • 二、问题分析
      • 2.1 redis-cli 登录
      • 2.2 info clients 查看连接数情况
      • 2.3 client list 查看具体连接情况
      • 2.4 分析连接空闲时长
      • 2.5 client list 根据客户端IP统计连接数
    • 三、问题结论和解决
      • 3.1 问题结论:
      • 3.2 解决方案①:优化程序
      • 3.3 解决方案②:扩大最大连接数
      • 3.4 解决方案③:杀死指定连接

一、问题介绍

我们在日常的开发过程中,经常会遇到 Redis 连接数不足 的情况,报错如下所示:

  • Caused by: org.redisson.client.RedisException: ERR max number of clients reached. channel
Caused by: org.redisson.client.RedisException: ERR max number of clients reached. channel: [id: 0xf10fcc26, L:/192.168.30.13:64137 - R:192.168.1.163/192.168.1.163:6379] command: (SELECT), params: [1]at org.redisson.client.handler.CommandDecoder.decode(CommandDecoder.java:365)at org.redisson.client.handler.CommandDecoder.decodeCommand(CommandDecoder.java:209)at org.redisson.client.handler.CommandDecoder.decode(CommandDecoder.java:147)at org.redisson.client.handler.CommandDecoder.decode(CommandDecoder.java:117)at io.netty.handler.codec.ByteToMessageDecoder.decodeRemovalReentryProtection(ByteToMessageDecoder.java:505)at io.netty.handler.codec.ReplayingDecoder.callDecode(ReplayingDecoder.java:366)at io.netty.handler.codec.ByteToMessageDecoder.channelRead(ByteToMessageDecoder.java:283)at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:374)at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:360)at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:352)at io.netty.channel.DefaultChannelPipeline$HeadContext.channelRead(DefaultChannelPipeline.java:1421)at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:374)at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:360)at io.netty.channel.DefaultChannelPipeline.fireChannelRead(DefaultChannelPipeline.java:930)at io.netty.channel.nio.AbstractNioByteChannel$NioByteUnsafe.read(AbstractNioByteChannel.java:163)at io.netty.channel.nio.NioEventLoop.processSelectedKey(NioEventLoop.java:697)at io.netty.channel.nio.NioEventLoop.processSelectedKeysOptimized(NioEventLoop.java:632)at io.netty.channel.nio.NioEventLoop.processSelectedKeys(NioEventLoop.java:549)at io.netty.channel.nio.NioEventLoop.run(NioEventLoop.java:511)... 4 common frames omitted

二、问题分析

ERR max number of clients reached. channel 报错是因为 Redis 的连接数不足 导致的。

2.1 redis-cli 登录

我们可以先使用如下命令登录 Redis 的客户端:

  • redis-cli -h 127.0.0.1 -p 6379 -c --raw

    -c:(cluster)选项是连接 Redis Cluster 结点需要使用的。-c 选项可以防止 movedask 异常。

    --raw:选项是反馈格式化后的结果,默认选项。相对应的是 --no-raw,即返回原始格式(二进制)。

2.2 info clients 查看连接数情况

查看 Redis 的当前连接数:

  • info clients
##版本6.2.4,相对5版本新增了部分显示信息##当前redis节点的客户端连接数
connected_clients:1
##集群的连接数
cluster_connections:0
##客户端最大连接数
maxclients:10000
##当前所有输入缓冲区中队列对象个数的最大值
client_recent_max_input_buffer:24
##当前所有输出缓冲区中占用的最大容量
client_recent_max_output_buffer:0
##正在执行阻塞命令的客户端个数
blocked_clients:0
tracking_clients:0
clients_in_timeout_table:0

2.3 client list 查看具体连接情况

查看 Redis 的具体连接情况:

  • client list

在这里插入图片描述

id=17750 addr=192.168.1.254:35864 laddr=172.17.0.3:6379 fd=9615 name= age=266661 idle=266661 flags=N db=2 sub=0 psub=0 multi=-1 qbuf=0 qbuf-free=0 argv-mem=0 obl=0 oll=0 omem=0 tot-mem=20504 events=r cmd=select user=default redir=-1
id=2575 addr=192.168.1.254:44133 laddr=172.17.0.3:6379 fd=1885 name= age=422195 idle=422195 flags=N db=2 sub=0 psub=0 multi=-1 qbuf=0 qbuf-free=0 argv-mem=0 obl=0 oll=0 omem=0 tot-mem=20504 events=r cmd=select user=default redir=-1
id=18212 addr=192.168.1.254:61386 laddr=172.17.0.3:6379 fd=9929 name= age=266308 idle=266308 flags=N db=2 sub=0 psub=0 multi=-1 qbuf=0 qbuf-free=0 argv-mem=0 obl=0 oll=0 omem=0 tot-mem=20504 events=r cmd=select user=default redir=-1
id=13437 addr=192.168.1.254:17625 laddr=172.17.0.3:6379 fd=6431 name= age=349287 idle=349287 flags=N db=2 sub=0 psub=0 multi=-1 qbuf=0 qbuf-free=0 argv-mem=0 obl=0 oll=0 omem=0 tot-mem=20504 events=r cmd=select user=default redir=-1
id=12730 addr=192.168.1.254:15535 laddr=172.17.0.3:6379 fd=6226 name= age=350448 idle=350448 flags=N db=2 sub=0 psub=0 multi=-1 qbuf=0 qbuf-free=0 argv-mem=0 obl=0 oll=0 omem=0 tot-mem=20504 events=r cmd=select user=default redir=-1
  • 官方文档: https://redis.io/docs/latest/commands/client-list/

client list 属性说明如下:

属性说明
id客户端连接ID
addr客户端连接IP和端口
laddrredis数据库连接地址和端口
fdsocket的文件描述符
name客户端连接名
age客户端连接存活时间
idle客户端连接空闲时间,单位秒。可以用于判断连接是否有没有被及时释放
flags客户端类型标识
db当前客户正在使用的数据库索引下标
sub/psub当前客户端订阅的频道或模式数
multi当前事务中已执行命令个数
qbuf输入缓冲区总容量
qbuf-free输入缓冲区剩余容量
argv-mem下一个命令的不完整参数(已从查询缓冲区中提取)
obl固定缓冲区的长度
oll动态缓冲区列表的长度
omem固定缓冲区和动态缓冲区使用的容量
tot-mem此客户端在其各个缓冲区中消耗的总内存
events文件描述符时间(r:可读;w:可写)
cmd当前客户端最后一次执行的命令,不包含参数
user用户名称,默认default
redir当前用户跟踪重定位的客户端ID

2.4 分析连接空闲时长

了解了以上的属性,我们再反观刚才 client list 的执行结果,可以看到:

  • 其中 idle(客户端连接空闲时间)和 age(客户端连接存活时间)的值基本一致,说明大部分的连接是没有用到的。

在这里插入图片描述

2.5 client list 根据客户端IP统计连接数

命令如下:

redis-cli -h 127.0.0.1 -p 6379 -c --raw client list | awk -F ' ' '{print $2}' | awk -F : '{print $1}' | sort | uniq -c | sort -nr | head -n 10

docker 命令版:

docker exec -it redis redis-cli client list | awk -F ' ' '{print $2}' | awk -F : '{print $1}' | sort | uniq -c | sort -nr | head -n 10

执行结果:

在这里插入图片描述


三、问题结论和解决

3.1 问题结论:

从上面的问题分析可以看出,问题原因是大部分连接被某一个IP占用导致的,可能是Redis最小连接数配置错误,或者程序Bug导致的。

3.2 解决方案①:优化程序

可以根据客户端的IP和端口定位到客户端的具体应用进行优化,但是如果客户端应用不是在你们部门维护的就不太好推进了。

3.3 解决方案②:扩大最大连接数

  • 方式一:redis.conf 配置文件中进行修改,如下所示:
# 设置最大连接数为10w
maxclients 100000
  • 方式二: 通过命令设置,如下所示:
config set maxclients 100000
  • 方式三: 启动 redis.service 服务时,添加参数 --maxclients 100000,如下所示:
redis-server --maxclients 100000 -f /ext/redis.conf
  • 验证: 使用命令查看最大连接数,如下所示:
config get maxclients

3.4 解决方案③:杀死指定连接

可以在 redis 中使用如下命令杀死指定连接:

# 方式一:通过ip:port杀死
client kill ip:port
# 方式二:通过连接ID杀死
client kill id 5299

可以使用如下命令针对指定 IP 的连接进行批量杀死,例如批量杀死192.168.1.123的 3 个连接:

redis-cli client list | grep '192.168.1.123' | awk -F ' ' '{print \$1}' | sed 's/id=//g' | head -n 3 | xargs -n 1 redis-cli client kill id
  • 如果需要杀死所有连接,可以去掉 head -n 3

docker 命令版:

docker exec -it redis sh -c "redis-cli client list | grep '192.168.1.254' | awk -F ' ' '{print \$1}' | sed 's/id=//g' | head -n 3 | xargs -n 1 redis-cli client kill id"
  • 注意1: 这里需要使用 sh -c 来包装整个命令,确保命令在一个子 shell 中执行,否则会报错: the input device is not a TTY
  • 注意2: 这里需要使用 xargs -n 1 来将 awk 筛选后的结果逐行执行,-n 1 用于确保逐行执行,否则会报错: (error) ERR syntax error
  • 如果需要杀死所有连接,可以去掉 head -n 3

整理完毕,完结撒花~🌻





参考地址:

1.Redis:13–常用功能之redis-cli redis-server等命令,https://cloud.tencent.com/developer/article/1784416
2.redis client list使用,https://blog.csdn.net/weixin_44375561/article/details/121955791
3.[问题分析]redis客户端连接数过多,大量空闲连接和readonly连接,https://segmentfault.com/a/1190000020256823

http://www.lryc.cn/news/456315.html

相关文章:

  • 八股文面试题总结(包含主流的面试经典题)
  • 一分钟掌握 Java22 新特性
  • 西安凭借入驻企业展示科技“硬”实力的数字媒体产业园
  • 【网络安全】利用XSS、OAuth配置错误实现token窃取及账户接管 (ATO)
  • 浙江所有省级医院体检报告查询上线浙里办!
  • 支付宝支付Java+uniapp支付宝小程序
  • Linux-磁盘优化的几个思路
  • 【第三版 系统集成项目管理工程师】第15章 组织保障
  • 从编程视角看生命、爱、自由、生活的排列顺序
  • Lumerical——属性编辑窗口的详解
  • 08实战篇:972应用题(2024)思路解析
  • 解决应用程序启动失败问题:由于找不到d3dx9_43.dll文件,如何快速有效地恢复和修复缺失的DLL组件
  • Ubuntu——双系统Ubuntu22.04系统安装和基础配置
  • stm32定时器中断和外部中断
  • LeetCode 每日一题 2024/9/30-2024/10/6
  • Redis篇(最佳实践)(持续更新迭代)
  • 详细介绍pandas 在python中的用法
  • 八字命理测算系统开发-源码搭建
  • Python批量读取mat文件
  • UE4 材质学习笔记05(凹凸偏移和视差映射/纹理压缩设置)
  • 基于贝叶斯决策的 CAD 程序设计方案
  • 算法: 二分查找题目练习
  • Qt开发技巧(十三)QList插入操作,扩展类型的使用,关于QSS的坑,Qt的延时方法,Qt编译的三种版本,环境搭建多练练,指向Qt源码的报错
  • docker快速上手
  • JAVA学习-练习试用Java实现“反转链表 II”
  • 15分钟学 Python 第35天 :Python 爬虫入门(一)
  • 【Qt】Qt学习笔记(一):Qt界面初识
  • Unity3D游戏的内存控制详解
  • 《数据结构》--栈【概念应用、图文并茂】
  • 国外电商系统开发-运维系统文件下载