必须调大net.core.somaxconn,因其默认值128远低于现代高并发需求,队列满后内核静默丢弃已完成三次握手的连接,导致客户端connection refused或超时;需同步调大该参数、redis tcp-backlog及ulimit -n,并重启redis生效。

Redis集群在高负载下丢连接,大概率不是Redis本身扛不住,而是Linux内核的TCP全连接队列溢出,net.core.somaxconn设太小是第一排查点。
为什么net.core.somaxconn必须调大?
Redis主线程负责accept(),但建连速度可能远超处理速度。已完成三次握手的连接会排队进“全连接队列”,队列满后内核直接静默丢弃——不发RST、不重传SYN-ACK,客户端只看到Connection refused或超时,tcpdump也抓不到异常包。
-
netstat -s | grep "listen overflows"输出非零(如listen overflows: 17)就是铁证 - 默认值常为128,而现代服务器轻松支撑万级并发,128完全不够用
- 这个参数和Redis的
tcp-backlog、进程ulimit -n必须协同生效,单改一个没用
怎么改才真正起作用?
三个条件缺一不可,否则改了等于白改:
- 临时生效:
sudo sysctl -w net.core.somaxconn=65535 - 持久化:
echo 'net.core.somaxconn = 65535' | sudo tee -a /etc/sysctl.d/99-redis.conf && sudo sysctl --system - Redis配置同步:6.2+ 版本在
redis.conf里加tcp-backlog 65535,老版本需确认glibc是否支持自动提升,否则可能仍卡在511
验证是否生效:ss -lnt | grep :6379,看Send-Q列是否显示65535(不是128或511)。
Redis 缓存和数据结构管理技能。通过自然语言操作 Redis,支持 String、Hash、List、Set、ZSet、Stream 等数据结构操作。当用户提到 Redis、缓存、消息队列、会话存储时使用此技能。
ss -lnt里Recv-Q持续非零说明什么?
Recv-Q是当前等待accept()的连接数,它长期大于0,意味着瓶颈不止在队列长度:
- 如果
Recv-Q接近Send-Q(比如65530/65535),说明队列确实压满,somaxconn还得再调大 - 如果
Recv-Q稳定在100~500且波动频繁,更可能是Redis自身卡住:查SLOWLOG GET有没有慢命令、INFO persistence看bgrewriteaof是否阻塞、INFO stats里instantaneous_ops_per_sec是否骤降
这时候调内核参数只是治标,得回过头看Redis主线程是不是被阻塞住了。
要不要动net.ipv4.tcp_max_syn_backlog?
这个参数管的是“半连接队列”(SYN_RCVD状态),只在遭遇SYN Flood攻击或极端短连接风暴时才有影响。Redis正常高并发场景下,它通常不是瓶颈:
- 除非压测时看到
netstat -s | grep "SYNs to LISTEN sockets dropped"非零,否则别碰它 - 盲目调大
net.ipv4.tcp_max_syn_backlog反而可能增加内存开销,且对Redis无实际收益 - 生产环境更该盯紧
net.core.somaxconn和tcp-backlog的匹配,这才是真实瓶颈所在
真正容易被忽略的是:哪怕somaxconn和tcp-backlog都设对了,如果Redis进程启动前没调ulimit -n,或者bind地址配成127.0.0.1而压测走的是公网IP,照样会丢连接——路径不一致,队列根本用不上。










