redis并发上不去、连接数卡在几千,大概率是linux内核限制了单进程文件描述符数或tcp连接队列长度;需调高ulimit -n、net.core.somaxconn和net.ipv4.tcp_max_syn_backlog,并通过systemd配置limitnofile永久生效。

为什么Redis并发上不去,netstat 看连接数卡在几千?
大概率是 Linux 内核限制了单进程可打开的文件描述符数量或 TCP 连接积压队列长度。Redis 是单线程事件驱动模型,所有客户端连接都靠 epoll(或 kqueue)监听,一旦 ulimit -n 太低,新连接会被内核直接拒绝,日志里可能只看到 accept: Too many open files 或干脆静默丢包。
-
ulimit -n默认通常为 1024,但 Redis 实例若要支撑 5000+ 并发连接,至少需设为 65536 或更高 - TCP 半连接队列(
net.ipv4.tcp_max_syn_backlog)和全连接队列(net.core.somaxconn)若太小,SYN 包会直接被丢弃,客户端表现为“连接超时”或“Connection refused”,ss -s中能看到synrecv队列溢出 - Redis 启动时不会校验这些值是否足够,只有真正高并发建连时才暴露问题
怎样永久修改文件句柄数(nofile)?
临时改 ulimit -n 65536 只对当前 shell 有效,Redis 用 systemd 启动时,必须通过服务单元配置注入限制。
- 编辑 Redis 服务文件:
/etc/systemd/system/redis-server.service(或/lib/systemd/system/redis-server.service),在[Service]段下添加两行:
LimitNOFILE=65536 LimitNPROC=65536
ulimit -n 命令到启动脚本里——systemd 会忽略 shell 级 ulimit 设置sudo systemctl daemon-reload && sudo systemctl restart redis-server
cat /proc/$(pgrep redis-server)/limits | grep "Max open files",看 Soft Limit 和 Hard Limit 是否已更新
net.core.somaxconn 和 net.ipv4.tcp_max_syn_backlog 怎么调?
这两个参数共同决定 Redis 能接受多少待完成的 TCP 连接。Redis 的 tcp-backlog 配置项(默认 511)只是告诉内核“我最多想处理这么多”,最终上限由内核参数硬性截断。
-
net.core.somaxconn控制全连接队列最大长度(已完成三次握手、等待accept()的连接),建议设为 65535 -
net.ipv4.tcp_max_syn_backlog控制半连接队列(收到 SYN、未完成握手),建议至少 65535,尤其在开启tcp_tw_reuse或面对突发 SYN 洪水时 - 临时生效:
sudo sysctl -w net.core.somaxconn=65535;永久生效需写入/etc/sysctl.conf:
net.core.somaxconn = 65535 net.ipv4.tcp_max_syn_backlog = 65535 net.ipv4.tcp_fin_timeout = 30
sudo sysctl -p 加载,再用 ss -lnt 查看 Recv-Q 列是否不再持续堆积Redis 日志和系统指标怎么交叉验证是否改到位?
光改参数不验证,等于没改。关键要看 Redis 是否真在用新限制,以及连接建立过程有没有被内核拦截。
- Redis 启动日志中搜
backlog,应显示类似:Server initialized with maxclients=65536, backlog=65535(说明tcp-backlog和somaxconn对齐了) - 压测时用
ss -s观察:total: 65535(全连接队列容量)、synrecv: 0(半连接无堆积)、estab: 60000+(稳定 ESTABLISHED 数) - 查错误计数:
grep -i "failed\|error" /var/log/redis/redis-server.log,重点关注accept相关失败;同时检查dmesg | tail -20,若有possible SYN flooding提示,说明tcp_max_syn_backlog仍不足 - 特别注意:如果 Redis 配置了
bind 127.0.0.1且压测走 localhost,Linux 会绕过部分网络栈,导致tcp_max_syn_backlog不起作用——务必用真实 IP 压测
最常被忽略的是 systemd 服务单元里的 LimitNOFILE 没配,或者 sysctl 修改后忘了 sysctl -p。这两个点一漏,前面所有操作都白忙。











