mysql连接数爆满本质是活跃连接总数超max_connections上限,而非用户超限;根因包括应用连接泄漏、短连接风暴、慢查询锁等待及配置不合理,需通过show processlist等命令定位并清理僵死连接。

主从模式下连接数超载,本质不是“主从架构导致的”,而是客户端连接管理不当 + 主从节点各自独立计数引发的叠加效应。直接调大 maxclients 通常治标不治本,甚至掩盖真实泄漏点。
为什么主从环境下连接数更容易爆满
主节点和每个从节点都维护独立的客户端连接池,maxclients 是单实例限制,不是集群总和。常见误操作包括:
- 应用配置了多个 Redis 地址(比如主 + 两个从),但没做读写分离路由,所有请求轮询打到全部节点——连接数 ×3
- 使用 JedisPool 或 Lettuce 连接池时,为每个节点单独 new 一个池,且未统一控制最大连接总数
- 从节点被误配为写入口(如配置指向从节点、代理未识别只读标记),触发
READONLY错误后重试逻辑不断建新连接 - 主从同步本身也占用连接:每个从节点对主节点建立一个
flags=M(master)连接,这部分不计入connected_clients,但消耗文件描述符
redis-cli client list 怎么快速定位“真凶”
别只看 connected_clients 数值,重点筛出异常连接特征:
Redis 缓存和数据结构管理技能。通过自然语言操作 Redis,支持 String、Hash、List、Set、ZSet、Stream 等数据结构操作。当用户提到 Redis、缓存、消息队列、会话存储时使用此技能。
- 执行
redis-cli -p 6379 client list后,用awk '{print $2}' | sort | uniq -c | sort -nr统计addr字段,找出连接数 TOP3 的客户端 IP - 对高连接数 IP,加条件过滤:
redis-cli -p 6379 client list | awk -F' ' '$2 ~ /10\.0\.5\.22/ && $5 > 3600 {print}'—— 查找来自10.0.5.22且age > 3600(1 小时)的连接,基本是泄漏源 - 检查
idle值持续 > 1800 且qbuf非零的连接,说明命令卡住未返回,可能因网络中断或客户端未 close
连接池配置必须避开的三个坑
Jedis/Lettuce 在主从场景下极易因配置错位导致连接堆积:
- 不要为每个节点配独立
maxTotal:例如主节点设 200、两个从各设 200,实际可能撑满 600 连接。应按业务读写比例统一分配,如写占 20%,则主池设 100,从池合计不超过 400 - JedisPool 的
setTestOnBorrow(true)在主从切换后可能失效——旧连接仍指向已降级的主节点,close()又不触发真实释放;建议改用setTestOnReturn(true)+ 自定义 validateObject - Lettuce 的
ClientResources共享问题:多个RedisClient实例若共用同一ClientResources,其内部事件循环线程和连接缓存会互相干扰;生产环境应为每类节点(主/从)分配独立ClientResources
临时救急但必须验证的 maxclients 调整
如果确认是瞬时峰值而非泄漏,可调高限制,但必须同步满足三条件,否则 Redis 启动时自动截断:
- 在
/etc/security/limits.conf中为 redis 用户添加:redis soft nofile 65536和redis hard nofile 65536 - 修改 systemd service 文件(如
/usr/lib/systemd/system/redis-server.service),增加:LimitNOFILE=65536 - 确认
/etc/pam.d/common-session或对应 PAM 配置中已启用pam_limits.so - 重启 Redis:
systemctl daemon-reload && systemctl restart redis-server,再验证:cat /proc/$(pidof redis-server)/limits | grep "Max open files"—— 必须看到65536,而非默认的1024
真正难处理的从来不是配置数字,而是那些 age 持续增长却始终不释放的连接——它们往往藏在异步回调、全局异常捕获或 finally 块里没被执行的 close() 中。










