tcp_mem三值分别控制TCP内存压力启动阈值(low)、主动回收警戒线(pressure)和硬限制(max),OOM主因常是pressure设置不当而非max过小;1:4:8比例适合高吞吐长连接,但小内存或低流量场景易致回收延迟与丢包雪崩;需同步调整tcp_rmem/tcp_wmem default值防空闲连接占满内存。

tcp_mem 的三个值到底怎么影响 OOM?
Linux 内核用 tcp_mem 三元组控制 TCP 内存总量上限和回收行为,不是简单“总内存除以 3”。第一个值是 per-socket 内存压力启动阈值(low),第二个是内核开始主动回收的警戒线(pressure),第三个是硬限制(max)。当频繁出现 TCP: out of memory,往往不是 max 太小,而是 pressure 设置不合理——内核还没来得及回收,就撞上 max 被丢包或阻塞。
常见错误现象:netstat -s | grep "memory" 显示大量 TCPOptimum 或 OutOfMemory 计数;ss -m 观察到大量 socket 的 rmem_alloc 接近 rcvbuf 却不释放;dmesg 出现 TCP: out of memory — consider tuning tcp_mem。
- 1:2:4 比例下,pressure 值偏低,内核过早启用 aggressive 回收(如丢包、缩减 cwnd),但实际内存未真正紧张,反而损害吞吐
- 1:4:8 比例拉宽了 low→pressure 的缓冲带,让内核更晚介入,适合高吞吐、长连接场景,但若 max 不足,仍会在 pressure 到 max 之间集中爆发 OOM
- 真正关键的是 pressure 和 max 的绝对差值:差值 131072 524288 1048576)
怎么验证当前 tcp_mem 是否成为瓶颈?
别只看 /proc/sys/net/ipv4/tcp_mem 数值,要结合实时内存分配状态。重点看 /proc/net/sockstat 中 TCP: 行的 mem 字段(单位页),它反映所有 TCP socket 当前真实内存占用,和 tcp_mem[2] 对比才有意义。
使用场景:在压测中每 5 秒采样一次:awk '/TCP:/ {print $3}' /proc/net/sockstat,同时记录 tcp_mem[2]。如果 mem 长期 > 0.9 × tcp_mem[2],且伴随 TCP: out of memory 日志,说明 max 确实卡脖子。
- 注意
sockstat的mem是页数,需 × 4KB 才是字节数,别和tcp_mem的数值直接比大小 -
tcp_mem单位是 page(默认 4KB),但它的值是“全局 TCP 内存页总数”,不是 per-socket - 如果
mem峰值常达tcp_mem[2]的 95% 以上,而tcp_mem[1](pressure)仅为其 40%,说明 pressure 太低,回收太激进
1:4:8 比例在什么负载下反而更糟?
不是比例越高越好。1:4:8 在小内存机器(≤ 4GB RAM)或大量低流量长连接(如 IoT 心跳)场景下,容易让 pressure 值虚高,导致内核长期不触发内存回收,最终在接近 max 时突然批量丢包、重传雪崩。
参数差异:假设物理内存 2GB,按 1:4:8 算出 tcp_mem = "32768 131072 262144"(≈128MB、512MB、1GB),但实际 TCP 内存可能只占 200MB,却因 pressure=512MB 一直不回收,bufferbloat 加剧,RTT 波动大。
- 小内存机器建议用 1:2:4,但把 max 设为物理内存的 10%~15%(如 2GB 机设
tcp_mem[2] = 262144≈ 1GB) - 高并发短连接(如 HTTP API)慎用 1:4:8,优先调低
net.ipv4.tcp_rmem/tcp_wmem的 default 值,减少单 socket 开销 - 检查
/proc/sys/net/ipv4/tcp_low_latency:设为 1 可让内核更倾向快速回收,部分抵消 high pressure 的迟钝
改完 tcp_mem 后必须同步调的两个参数
单独调 tcp_mem 很少治本。它只是总闸门,下面还有 per-socket 的水龙头——tcp_rmem 和 tcp_wmem。如果它们的 default 值过大(比如默认 256KB),而 tcp_mem 又设得很宽松,大量空闲连接会默默占满内存,直到突发流量才暴露问题。
性能影响:未同步调整时,即使 tcp_mem 改成 1:4:8,ss -i 仍可能显示大量 socket 的 rcv_ssthresh 卡在 64KB,这是内核因内存压力被迫压低接收窗口的表现,本质还是底层 buffer 分配失控。
- 务必检查
/proc/sys/net/ipv4/tcp_rmem:三个值分别对应 min/default/max,default 建议 ≤tcp_mem[0]÷ 1000(例如tcp_mem[0]=131072页 ≈ 512MB,则 default ≤ 512KB) -
tcp_wmem的 default 值同样需约束,尤其在高丢包链路,过大的 default 会加剧重传缓冲堆积 - 改完后运行
echo 1 > /proc/sys/net/ipv4/tcp_retries2(临时降低重试次数),避免旧连接在新内存策略下拖慢整体恢复
sockstat 的 mem 曲线是否平滑、ss -s 的 memory 行是否不再频繁触顶——真正的稳定,是压力来了有缓冲,压力走了能及时腾空。










