Connection refused通常不是epoll句柄耗尽的直接表现,而是服务未启动、防火墙拦截、bind配置错误等更常见原因所致;仅当排除这些后,结合ss端口不监听、dmesg报Too many open files、INFO中rejected_connections增长等现象,才需排查文件描述符限制、maxclients配置及tcp-keepalive等深层因素。

Redis 出现 Connection refused 报错,**通常不是 epoll 句柄耗尽的直接表现**——epoll 耗尽本身不会让 Redis 主动拒绝新连接并返回 “Connection refused”,而是更可能引发 accept() 失败、连接堆积、超时、或服务假死,最终表现为客户端连不上(看似 Connection refused),但真实原因藏得更深。
先确认是不是 epoll 句柄问题
Connection refused 的常见根因(服务未监听、防火墙拦截、bind 配置错误等)必须优先排除。只有当这些都排除后,且出现以下组合现象,才需怀疑 epoll 或底层文件描述符(fd)资源枯竭:
- Redis 进程仍在运行(
ps可见),但ss -tlnp | grep 6379或netstat -tlnp | grep 6379显示端口 不再监听 或监听状态异常(如 LISTEN 但无进程名) - 系统日志中频繁出现
Too many open files、Cannot allocate memory或accept: Too many open files类似报错(查dmesg -T | tail -20或journalctl -u redis --since "1 hour ago" | grep -i "file\|open\|accept") - Redis INFO 输出中
connected_clients接近甚至超过maxclients,而rejected_connections持续增长 -
cat /proc/$(pgrep redis-server)/limits | grep "Max open files"显示Limit值极低(如 1024),且Max open files的Soft值已被打满
检查并提升系统级文件描述符限制
epoll 本身不“耗尽句柄”,但它依赖的底层 fd 资源是有限的。Redis 每个客户端连接、每个定时器、每个后台 RDB/AOF 文件操作都会占用 fd。若系统限制太低,Redis 在创建新 socket 或打开持久化文件时就会失败。
Redis 缓存和数据结构管理技能。通过自然语言操作 Redis,支持 String、Hash、List、Set、ZSet、Stream 等数据结构操作。当用户提到 Redis、缓存、消息队列、会话存储时使用此技能。
- 查看当前 Redis 进程的 fd 限制:
cat /proc/$(pgrep redis-server)/limits | grep "Max open files" - 临时提高(仅当前会话):
ulimit -n 65536(需在启动 Redis 前执行) - 永久生效(推荐):
- 编辑
/etc/security/limits.conf,添加两行:redis soft nofile 65536redis hard nofile 65536
(假设 Redis 以用户redis运行;若用 root 或 systemd 启动,需对应调整用户名) - 确保
pam_limits.so已启用(检查/etc/pam.d/common-session或/etc/pam.d/sshd是否含session required pam_limits.so) - 重启 Redis 服务(systemd 下需 reload daemon:
sudo systemctl daemon-reload && sudo systemctl restart redis)
- 编辑
检查 Redis 自身配置与连接管理
即使系统 fd 上限足够,Redis 若配置不当,仍会快速占满可用 fd:
- 确认
maxclients设置合理:redis-cli config get maxclients。默认值通常是 10000,但如果系统 ulimit 只有 1024,实际生效值会被截断为 1024−32(预留系统 fd)。建议设为 ulimit soft limit − 256 - 检查是否有大量短连接未释放:用
redis-cli info clients查看connected_clients和client_longest_output_list。若前者高、后者也高,说明存在 client buffer 积压,可能因客户端未及时读响应导致连接 hang 住 - 启用
tcp-keepalive(如tcp-keepalive 300)可主动探测和清理僵死连接,缓解 fd 泄漏 - 避免在配置中开启不必要的功能(如
notify-keyspace-events全开),它们会额外创建内部 fd
验证 epoll 相关内核参数(较少见,但高并发场景需关注)
Linux 内核对 epoll 实例数及每个实例监控的 fd 数也有上限,不过 Redis 单实例只用一个 epoll 实例,极少触达此限。仅当单机部署大量 Redis 实例或混布其他高 fd 应用时才需检查:
-
cat /proc/sys/fs/epoll/max_user_watches—— 默认常为几十万,一般无需调大 -
cat /proc/sys/fs/file-max—— 系统级总 fd 上限,应远大于所有进程 fd 之和(建议 ≥ 2× 总预期 fd) - 若确需调整,可临时写入:
echo 2097152 > /proc/sys/fs/file-max;永久配置加到/etc/sysctl.conf中
真正由 epoll 层面直接导致 Connection refused 的情况极为罕见。绝大多数所谓“epoll 耗尽”问题,本质是 文件描述符耗尽 + Redis 无法 accept 新连接 + 端口监听失效。按上述顺序排查 fd 限制、Redis 配置、连接行为和系统日志,就能准确定位并解决。

















