记录 redis 端口的坑,高并发请求常见的问题分类

Redis 连接池配置不当导致 TIME_WAIT 暴涨、端口被打满的排查与优化

前言

最近线上服务出现了一个比较典型的问题------服务器端口被打满,导致新连接无法建立。排查后发现根因是 Redis 客户端连接池配置不合理,产生了大量短连接,进而导致 TIME_WAIT 状态的连接持续堆积。

这里记录一下整个排查和优化过程,希望能帮到遇到类似问题的同学。

问题现象

线上告警显示服务出现连接异常,登录服务器后通过 netstat 统计 TIME_WAIT 状态的连接数:

bash 复制代码
netstat -ant | awk '$6=="TIME_WAIT"{c++} END{print c}'

多次执行后发现,TIME_WAIT 连接数在持续攀升:

复制代码
22644
22934
23499
22640
22775
24984
25503
26096
25853
26123
26630
27101
27518
27791
27146
27327
27858
28190
28638
28033

22k 一路涨到 28k+ ,而且没有回落趋势。Linux 默认的本地端口范围是 32768~60999,大约 28000 个端口,此时已经接近打满。

原因分析

排查发现问题出在 Redis 客户端的连接池配置上。原来的配置如下:

go 复制代码
RdbClient = redis.NewClient(&redis.Options{
    Addr:         host + ":" + port,
    Password:     pass,
    DB:           db,
    PoolSize:     100,
    MinIdleConns: 10,
    MaxIdleConns: 20,
})

这个配置存在几个关键问题:

1. PoolSize 过小

PoolSize: 100 意味着连接池最多持有 100 个连接。在高并发场景下,100 个连接远远不够用。当池内连接全部被占用时,客户端会创建新的连接来处理请求,而这些临时连接用完就关闭,变成了短连接。

2. 空闲连接管理不合理

MinIdleConns: 10MaxIdleConns: 20 让连接池对空闲连接的保留非常"吝啬"。大量连接在空闲后迅速被回收,等下一波请求来了又得重新建连,造成连接的频繁创建和销毁

3. 缺少空闲超时配置

没有设置 ConnMaxIdleTime,导致空闲连接的生命周期管理缺失。

核心矛盾

连接池容量不足 + 空闲连接回收过激 → 大量短连接 → TCP 四次挥手后进入 TIME_WAIT → TIME_WAIT 堆积 → 端口耗尽

简单回顾一下 TCP 的 TIME_WAIT 机制:主动关闭连接的一方会进入 TIME_WAIT 状态,默认持续 2 × MSL(通常 60 秒)。在这段时间内,这个端口是不可复用的。所以短连接越多,TIME_WAIT 堆积越严重。

优化方案

调整后的 Redis 客户端配置:

go 复制代码
RdbClient = redis.NewClient(&redis.Options{
    Addr:               host + ":" + port,
    Password:           pass,
    DB:                 db,
    PoolSize:           poolSize,          // 可配置,按实际负载调整
    MinIdleConns:       0,                 // 不强制维护空闲连接
    ConnMaxIdleTime:    idleTimeout,       // 空闲连接超时释放
    MaxActiveConns:     poolSize * 2,      // 限制最大活跃连接数
    MaxConcurrentDials: 10,                // 限制并发建连数
})

逐项说明:

参数 调整内容 目的
PoolSize 固定值 → 可配置变量 根据业务实际并发量灵活调整
MinIdleConns 10 → 0 避免维护不必要的空闲连接,减少资源浪费
ConnMaxIdleTime 无 → idleTimeout 让空闲连接有序超时释放,而非突然被回收后又立即重建
MaxActiveConns 无 → poolSize * 2 给活跃连接加上天花板,防止突发流量下无限制创建新连接
MaxConcurrentDials 无 → 10 限制并发建连的协程数,避免瞬间大量 dial 造成系统抖动

关键思路就是:提高连接复用率,减少短连接的产生。

效果

优化上线后,TIME_WAIT 连接数明显下降并趋于稳定,端口耗尽的问题不再出现。

小结

几个 takeaway:

  • Redis 连接池的 PoolSize 一定要根据实际并发量合理设置,不要拍脑袋给个固定小值
  • MinIdleConnsMaxIdleConns 配置不当会导致连接频繁创建销毁,反而得不偿失
  • 别忘了配置 ConnMaxIdleTime,让空闲连接的回收有章可循
  • MaxActiveConns 可以作为最后一道防线,防止连接数失控
  • 遇到端口耗尽问题,先用 netstat 看 TIME_WAIT 数量,往往就能找到方向

希望这篇排查记录能对你有所帮助,如果有更好的优化思路,欢迎在评论区交流 🙌

相关推荐
我叫黑大帅7 小时前
PHP中的官方操作数据库PDO
后端·面试·php
用户92239610327287 小时前
不用 nohup、不用 sshpass!rsync 后台传输 + 断 SSH 不中断的原生玩法
后端
青柠代码录7 小时前
【SpringBoot】过滤器
后端
元宝骑士7 小时前
MySQL联表查询优化实战:小表驱动大表的联合索引设计
后端·mysql
用户69371750013848 小时前
Android 开发,别只钻技术一亩三分地,也该学点“广度”了
android·前端·后端
gogogo出发喽8 小时前
使用Pear Admin Flask
后端·python·flask
hhhhhaaa8 小时前
SpringBoot 自定义参数解析器实现请求统一封装实践
后端
何陋轩8 小时前
Java线程池从入门到精通:框架自带 vs 自定义,我该怎么选?
后端
货拉拉技术9 小时前
数据质量告警平台的建设与应用实践
后端
m0_694845579 小时前
UVdesk部署教程:企业级帮助台系统实践
服务器·开发语言·后端·golang·github