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

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

相关推荐
aurora_zjj3 分钟前
一次持续 3 年的 OpenResty 死循环排查:最终定位到 LuaJIT ARM64 的一条汇编指令
后端
智驭未来掌门人5 分钟前
动态平台雷达目标引导系统设计与实现
后端
Bazingga7 分钟前
一次Agent超时熔断设计踩过的坑
后端
Lyy8 分钟前
DevOps平台 — 第十九篇:消息通知与预警的设计与实现
后端·devops·vibecoding
IT_陈寒1 小时前
React的setState真是个演员,你以为它同步其实在装睡
前端·人工智能·后端
ServBay2 小时前
Claude Fable 5.5 测试曝光,但它在悄悄给你打分
后端·ai编程·claude
IT规划师3 小时前
一文讲透五种发布机制:滚动、蓝绿、金丝雀、红黑与 AB
后端·面试
一条Go4 小时前
两套权限目录,三重闸门:Alioth 的多租户 RBAC 为什么这么拧
后端·程序员·github
Tokenfree4 小时前
把多模态 OCR 接进业务系统:四千张运单,三个坑
后端
用户859313061354 小时前
我给 AI Agent 写了个下载器:293KB 的网页,不再吃掉 7 万 token
后端