简介面向 Linux 系统管理员、运维工程师与后端开发者的操作系统调优参数速查文档主要服务于高并发网络场景下 TCP/IP 行为优化。文档逐一解析 /proc/sys/net/core 下的 rmem_max、wmem_max说明如何通过增大缓冲值提升大流量下的接收与发送能力又对 /proc/sys/net/ipv4 下 tcp_timestamps、tcp_sack、tcp_window_scaling 做了展开时间戳会带来十二字节额外开销但有助于计算往返时间选择性应答能优化丢包重传窗口扩展则突破六十五千字节限制、提升带宽利用率。同时覆盖 /proc/sys/fs 的超级块参数以及 /proc/sys/kernel 下 acct、ctrl-alt-del 等内核控制项并给出写入 /etc/rc.local 或 /etc/sysctl.conf 的持久化方式例如将接收与发送缓冲设置为 256960。文档还提醒/proc 下的修改重启后会丢失调整前应先做基准测试避免不当配置造成性能波动甚至系统不稳定。资源仅含 1 个 docx 文档、18KB内容以文字说明与配置示例为主已有 312 人学习/下载既可作为快速查阅关键参数的清单也适合逐项验证时形成个人调优笔记是服务器性能排查与优化前的一份实用参考。1. Linux 调优参数到底在调什么不换硬件也能救回来的那部分性能做运维头三年我一直以为“调优”是玄学直到有一回线上 Kafka 集群在流量高峰集体卡顿CPU 和内存都有余量但请求就是堆积。排到最后发现是net.core.somaxconn和vm.min_free_kbytes这种平时根本没人看的参数在拖后腿。从那以后我养成了习惯新环境上线前先按业务特征把/etc/sysctl.conf和/sys/block/*/queue/scheduler过一遍而不是等出故障再翻内核文档。这套“Linux 操作系统调优参数”并不神秘它是一组内核运行时行为的开关覆盖内存回收策略、文件系统缓存回写、网络协议栈缓冲、IO 调度算法、进程调度与文件句柄限制。适合谁三类人一是被线上延迟毛刺折磨的应用运维二是准备压测报告却发现性能上不去的测试工程师三是刚接手服务器不知道从哪里下手的 SRE 新人。把它当成一套检查清单和参数语义手册来用比背命令有效得多。下面我会按“先分清三件套vm、fs、net→ 再看磁盘 IO 调度 → 调完怎么验证”的顺序把我用过、踩过、复盘过的参数逐一拆开讲。每个参数我都会给出适用的业务场景、建议值、改完看什么指标以及翻车现场长什么样。这中间有一些是我自己的血泪经验不是从 man page 抄来的。2. 内核三件套vm、fs、net 这三大类参数分别管什么事2.1 vm 系列内存回收与脏页回写决定你的应用是“顿挫”还是“丝滑”vm前缀的参数管的是虚拟内存子系统也就是页分配、页回收、脏页回写和 OOM 行为。这一组参数是调优里最容易见效也最容易翻车的因为改动后不会立刻报错而是延迟几十分钟甚至几小时才在业务曲线上体现出来。我一般最先动的是vm.swappiness。这个参数控制内核“有多倾向于把匿名内存页换到 swap”取值范围 0-200默认通常是 60。数值越高内核越积极换出内存页越低越倾向于保留在物理内存里。对于跑 Java、Python 这类带 GC 的应用换出 JVM 堆的页会导致 Full GC 时卡顿明显所以很多人一上来就设 0。但这里有个坑设 0 并不是“禁用 swap”而是“只在内存极度紧张时才换出”。如果机器同时跑着数据库和构建任务设 0 反而可能在突发内存压力时触发 OOM因为内核没法快速回收足够多的页。我的建议是纯 Web 应用或无状态服务设 10-20数据库主机设 1-10混部机器不要低于 20。然后是脏页回写相关的三个参数它们决定“数据在内存里攒多久才落盘”# 查看当前值 sysctl vm.dirty_ratio vm.dirty_background_ratio vm.dirty_writeback_centisecs # 临时修改重启失效 sysctl -w vm.dirty_ratio20 sysctl -w vm.dirty_background_ratio10 sysctl -w vm.dirty_writeback_centisecs500 # 持久化写入 echo vm.dirty_ratio 20 /etc/sysctl.conf echo vm.dirty_background_ratio 10 /etc/sysctl.conf echo vm.dirty_writeback_centisecs 500 /etc/sysctl.conf sysctl -pvm.dirty_background_ratio是后台回写阈值到达这个比例后内核会在后台慢慢刷盘不阻塞应用。vm.dirty_ratio是强制同步阈值到达后应用写操作会被阻塞直到刷盘完成。这两个参数必须拉开差距dirty_background_ratio建议设成dirty_ratio的一半左右。如果两个都设成 20意味着脏页到 20% 时后台开始刷同时 20% 也是强制阈值应用会频繁被阻塞写入表现就是“写入延迟抖动”。我踩过这个坑当时把两个都设成 30结果混合读写压测时 fio 的 p99 延迟从 20ms 飙到 800ms。2.2 fs 系列文件句柄与 inode 缓存高并发连接数的隐形瓶颈fs前缀参数管文件系统相关内核行为最常调的是文件句柄上限和 inode 缓存。很多高并发服务明明改了ulimit -n却还是报 “too many open files”原因就是没改内核层的fs.file-max。# 查看当前限制 cat /proc/sys/fs/file-max cat /proc/sys/fs/file-nr # 临时调整 sysctl -w fs.file-max2097152 sysctl -w fs.nr_open2097152 # 持久化 echo fs.file-max 2097152 /etc/sysctl.conf echo fs.nr_open 2097152 /etc/sysctl.conf sysctl -pfs.file-max是系统级最大文件句柄数fs.nr_open是单个进程能打开的最大句柄数的硬上限。光改file-max不改nr_open进程还是会被nr_open默认 1048576卡住。file-nr的前两个数字分别是已分配和未分配的句柄数监控建议盯第一个数字和file-max的占比超过 70% 就要扩容了。fs.inotify.max_user_watches也是容易被忽视的参数。如果你用tail -F监控日志、跑着node-sass或webpack这类依赖 inotify 的工具文件数一多就会报 “inotify watch limit reached”。默认 8192 太小做前端构建或日志采集的机器建议调到 524288。echo fs.inotify.max_user_watches 524288 /etc/sysctl.conf sysctl -p调完 inotify 参数要重启对应的用户进程才生效不用重启机器。这个参数我建议直接写进基线配置因为它不会带来副作用只会让需要 inotify 的程序少报错。2.3 net 系列连接队列与缓冲区延迟毛刺的常见根源网络协议栈的参数比 vm 和 fs 复杂因为涉及 TCP/IP 的状态机。我调得最多的是三类连接队列长度、读写缓冲区、TIME_WAIT 回收。net.core.somaxconn控制全连接队列长度应用通过listen(fd, backlog)传入的 backlog 会被内核截断到somaxconn以内。如果你用 Nginx 做反代、连接数大且短这个参数不调大客户端会间歇性出现 “Connection reset” 或握手超时。常见做法是调大到 4096 或 65535同时 Nginx 配置里的listen 80 backlog4096也要改否则 Nginx 自己传的 backlog 还是默认值。net.ipv4.tcp_rmem和net.ipv4.tcp_wmem是三元组最小值、默认值、最大值控制 TCP 收发缓冲区。对吞吐敏感的业务把默认值调大能减少小包聚合的开销sysctl -w net.ipv4.tcp_rmem4096 87380 6291456 sysctl -w net.ipv4.tcp_wmem4096 16384 6291456 sysctl -w net.core.rmem_max6291456 sysctl -w net.core.wmem_max6291456这里要注意tcp_rmem/tcp_wmem是每个 socket 的缓冲不是全局限额rmem_max/wmem_max才是系统级上限。调大后要观察内存占用每条 TCP 连接多占几 MB如果有几十万连接就是几十 GB 的内存开销。所以不建议无脑调到最大而是先用ss -m看当前连接的实际缓冲占用再决定。net.ipv4.tcp_tw_reuse允许新连接复用 TIME_WAIT 状态的连接对短连接密集的转发服务有帮助。但前提是机器没有做 NAT、也没有启用tcp_timestamps的异常场景。我曾经在一台负载均衡器上开启后出现连接复用错乱排查了一整天才发现是对方服务端 TCP 时间戳异常后来只在内网直连场景才用它。3. 磁盘与 IO 调度scheduler、nr_requests 和预读参数到底怎么选3.1 先识别磁盘类型再选 scheduler别让 SSD 跑着 HDD 的队列算法大多数云主机和物理机的磁盘类型决定了你该用哪种 IO 调度器。传统机械盘用mq-deadline多队列时代替代了deadline普通 SSD 用none即 noopNVMe 也是none。判断当前调度器cat /sys/block/sda/queue/scheduler如果输出类似[mq-deadline] none中括号里就是当前生效的调度器。改法有两种临时改直接写 sysfsecho none /sys/block/sda/queue/scheduler持久化要装util-linux的schedset或写 udev 规则但常见做法是用 grub 内核参数在/etc/default/grub的GRUB_CMDLINE_LINUX里加elevatornone然后执行update-grub并重启。注意现代内核里elevatornone只对没有明确指定调度器的块设备生效。选调度器的逻辑不复杂数据库和虚拟化宿主机这类需要“公平排队”的场景mq-deadline能减少个别大 IO 饿死小 IO单纯跑 Web 或大数据计算none让块设备层直接把 IO 下发到底层减少一层排队开销。我见过有人给全闪存阵列配mq-deadline还调低nr_requests结果 IO 排队深度变浅延迟没降反升了。3.2 nr_requests 与预读调完看 iostat 的 await 和 svctmnr_requests是块设备请求队列里最多排队的 IO 请求数。它像是一个水龙头限制了能同时灌给底层驱动的请求量调小会降低峰值吞吐、但能缩短排队延迟调大则相反吞吐上来但延迟变高。修改方式# 查看当前队列深度 cat /sys/block/nvme0n1/queue/nr_requests # 调大队列深度适合高吞吐批量读写的业务 echo 512 /sys/block/nvme0n1/queue/nr_requests持久化用 udev 规则比较靠谱。在/etc/udev/rules.d/60-io-scheduler.rules里写ACTIONadd|change, KERNELnvme[0-9]n[0-9], ATTR{queue/nr_requests}512然后udevadm control --reload udevadm trigger。改完用iostat -x 1看awaitIO 平均处理耗时和%util。如果%util已经接近 100%调大nr_requests没有意义瓶颈在设备本身。如果await高、%util只有 50%说明是排队问题这时调大nr_requests或者换mq-deadline更有效。预读参数read_ahead_kb控制顺序读时内核提前加载多少数据到页缓存范围 0-8192KB。顺序读为主的大数据场景比如日志分析、视频转码建议调 4096随机读为主的数据库建议调回 256 或直接设 0否则多读的部分全是浪费带宽。改法echo 4096 /sys/block/sdb/queue/read_ahead_kb3.3 挂载参数noatime 和 commit 要分开用别一刀切文件系统挂载参数经常和内核参数混在一起讨论但它们的生效位置不同。mount -o noatime让读文件时不更新访问时间戳能减少大量元数据写操作对任何读多场景都建议加。commit参数控制 ext4/xfs 的日志提交间隔默认 5 秒调大到 30 秒能减少磁盘写次数但掉电时可能丢失更多数据数据库数据盘我从不改 commit日志盘和缓存盘会调大。检查当前挂载参数mount | grep -E ext4|xfs临时改需要重新挂载生产环境建议写/etc/fstab后重启或mount -o remount# 只改 noatime不碰 commit mount -o remount,noatime /data有一个特别容易翻车的组合对 SSD 开discard挂载参数对老内核版本会导致严重的卡顿。现代内核建议用fstrim定时任务替代挂载参数里的discard避免每条删除操作都触发 trim 指令。这块没有标准答案我一般是 SSD 主机每个星期跑一次fstrim -av而不是挂载时加 discard。4. 进程与内存边界参数从 OOM 到 CPU 隔离从“能用”到“可控”4.1 overcommit 策略与 OOM 评分让该活下来的进程活下来vm.overcommit_memory和vm.overcommit_ratio决定了内核对内存申请的“审批”宽松度。取值 0 表示启发式1 表示永远通过2 表示超过“物理内存×ratio”就拒绝。对大内存应用比如 Elasticsearch、ClickHouse我建议设成 2 并配ratio80好处是 malloc 等预分配大块内存时不会被 OOM 随机杀死而是在申请阶段就明确失败坏处是有些程序不做错误处理直接崩溃所以要结合进程oom_score_adj一起用。sysctl -w vm.overcommit_memory2 sysctl -w vm.overcommit_ratio80 echo vm.overcommit_memory 2 /etc/sysctl.conf echo vm.overcommit_ratio 80 /etc/sysctl.conf sysctl -p这里有个细节overcommit_memory1会让malloc永远返回成功但真正访问内存时才可能被 OOM killer。很多 Java 用-Xmx设大堆物理内存不够时启动不报错跑几天后突然进程消失就是被 OOM killer 干的。解决办法是给关键进程设oom_score_adj# 查看 Java 进程 pid pidof java # 设置权重-1000 表示 OOM 时尽量不杀 echo -1000 /proc/$(pidof java)/oom_score_adj持久化做法是用 systemd service 文件的OOMScoreAdjust-1000而不是写在 rc.local 里。4.2 内核参数中的 CPU 可调项isolcpus 和 NOHZ压测场景才值得碰isolcpus把指定 CPU 核从内核调度器中隔离出来只有显式绑定到这些核的进程能跑。这个参数适合两类场景一是 DPDK 或音频处理这类需要无干扰的实时任务二是压测工具想排除内核进程干扰。隔离后要配合irqaffinity把中断也挪走# 内核引导参数 isolcpus4-7 nohz_full4-7 rcu_nocbs4-7这是在/etc/default/grub的GRUB_CMDLINE_LINUX里加的改完update-grub重启。注意nohz_full让这些核尽可能不接收时钟中断但需要内核配置了CONFIG_NO_HZ_FULL。大部分云主机内核开了但如果你用的是发行版默认内核且没装kernel-rt之类的包不一定支持这些引导参数。设置了isolcpus后系统里普通进程真的不会再跑到这些核上如果你没绑核就白白浪费了 CPU所以只建议在专用压测机或实时业务上做。kernel.sched_autogroup开启后调度器按会话管理任务组适合多用户登录的开发机避免一个人跑任务把整机拖死。生产服务器关掉它更直观sysctl -w kernel.sched_autogroup1这个参数不算核心调优点但开发机场景很实用。4.3 NUMA 相关的内存分配策略数据库和 JVM 要单独看多路服务器的 NUMA 架构下kernel.numa_balancing默认开启。它会定期把内存页迁移到访问它的 CPU 所在 NUMA 节点代价是周期性的迁移开销。对延迟敏感的大型 Java 应用建议关闭它并配合 JVM 的-XX:UseNUMAsysctl -w kernel.numa_balancing0关掉之后结合numactl --hardware的分布看内存分配情况如果内存跨 node 分配严重用numactl --interleaveall启动应用来平衡带宽。这个参数对单路机器毫无意义对两路及以上的机器收益明显。线程限制kernel.threads-max对应线程数上限正常不用调除非跑容器编排或大量线程的 RPC 服务。查看当前线程数ps -eLf | wc -l如果这个数长期超过threads-max的 70%才考虑把它调高。但更常见的是vm.max_map_count不够导致 Elasticsearch 报 “max virtual memory areas vm.max_map_count is too low”默认 65530ES 至少要求 262144。echo vm.max_map_count 262144 /etc/sysctl.conf sysctl -p5. 调优参数避坑指南5 个最常见的翻车现场5.1 swappiness 设为 0 后JVM 在内存压力下被 OOMKilled现象给一台 64G 内存的机器设了vm.swappiness0跑着微服务网关某天流量上来后 Java 进程突然消失dmesg里看到 OOM killer 日志。那时候物理内存并没有完全用满但已经是内存挤压状态内核宁愿杀进程也不换出匿名页。原因swappiness0让内核尽量不用 swap但内存挤压时需要快速回收页swap 走不通就只能走 OOM。尤其 Java 进程的堆全是匿名页回收速度慢很容易成为被杀目标。解决把swappiness改为 10并给关键进程配oom_score_adj-500到 -1000同时确保 swap 分区或 swapfile 至少有一小部分可用比如 4G。这不算浪费是给内核一条退路。5.2 dirty_ratio 和 dirty_background_ratio 设成相同值写入延迟飙升现象压测工具跑混合读写测试写入延迟 p99 从 20ms 升到 800msiostat 显示w_await很高但磁盘本身利用率只有 60%。原因两个阈值设成相同值后写入过程一开始就把脏页攒到阈值应用写操作立即被阻塞触发同步回写。解决把dirty_background_ratio设成dirty_ratio的 50% 左右。比如 ratio30background15。改完观察/proc/vmstat里的nr_dirty和nr_writeback确保 writeback 平缓波动。关键教训是这两个参数必须拉开差距这是很多人第一次调就踩的坑。5.3 修改 tcp_tw_reuse 后出现连接复用错乱业务偶发数据串包现象一台内网转发服务开启net.ipv4.tcp_tw_reuse1后偶发出现 HTTP 请求返回异常日志里能看到连接被复用后延迟突然变高。原因tcp_tw_reuse需要配合 TCP 时间戳正常工作。对端服务器如果关闭了时间戳或时间戳回拨复用的连接就会出现序列号异常。常见于经过 NAT 的链路或对端是老旧内核。解决先执行sysctl -w net.ipv4.tcp_tw_reuse0恢复然后检查链路是否经过 NAT。建议只在纯内网直连且双方系统一致的环境中开启否则不要碰这个参数。现代内核的 TIME_WAIT 处理能力已经不差调大tcp_max_tw_buckets比开启 reuse 更安全。5.4 nr_requests 调大后 SSD 延迟反而升高现象给 NVMe 盘把nr_requests从 256 调到 1024fio 随机读测试的 p99 延迟反而从 1ms 升到 3ms。原因NVMe 盘本身队列深度很高块设备层再放大排队请求在驱动和设备之间形成积压。队列深度越高排队等待时间越长。解决对 NVMe 和高端 SSD保持nr_requests默认或只调到 256不要超过 512。真正的瓶颈通常在应用层 IO 深度而不是块设备队列。判断方法是看iostat -x的avgqu-sz如果它持续大于nr_requests的一半才有调大的必要。5.5 修改 sysctl.conf 后重启系统配置丢失现象改了/etc/sysctl.conf并执行sysctl -p生效但重启后参数回到默认值。原因可能是发行版使用了/etc/sysctl.d/目录下的配置文件且同名 key 在/usr/lib/sysctl.d/里有更高优先级也可能是sysctl.conf里写错了格式比如缺少空格或用了中文注释导致解析失败。解决用systemd的配置检查确认systemd-analyze verify /etc/sysctl.conf sysctl --system把所有自定义参数放在/etc/sysctl.d/99-custom.conf里并确保文件名前缀比发行版自带的50-、60-更靠后即优先级更高。修改后执行sysctl --system重新加载不要用sysctl -p旧命令去加载新目录下的文件否则会漏掉不在/etc/sysctl.conf里的配置。6. 验证调优效果先用压测工具量化“改前 vs 改后”再按照业务指标调参很多人改完参数不验证过几天业务出问题就怀疑是自己的问题但又不敢回滚。我的做法是每次调优前先用工具把基线数据打出来然后小步改动、每一步都量化验证最后再固化到配置管理工具里。这一步才是调优动作的闭环。这里给出一个最小验证组合# 内存和脏页状态 vmstat 1 10 # IO 延迟和队列深度 iostat -x 1 5 # TCP 连接状态 ss -s压测工具方面磁盘用fio网络用iperf3或wrk。跑 fio 时记录四组数毛刺基准随机读、随机写、混合读写、顺序读。每次只改一个参数重新跑同样的压测命令对比前后 n 组的p99延迟和IOPS。这里有个关键点压测时间不要太短。IO 参数改动对缓冲和回写的影响会延迟几分钟才完全体现至少压 5 分钟以上。验证 CPU 隔离或进程绑核时用perf stat看上下文切换perf stat -e context-switches,cpu-migrations sleep 10cpu-migrations应该显著下降否则说明isolcpus没有真正生效或中断没迁移干净。还有一个小技巧是用taskset -pc $$查看当前 shell 允许的 CPU 集合快速确认隔离是否生效。参数固化的顺序我是这样做的先在测试机改好跑通验证然后写进配置管理Ansible 或脚本模板最后在预发环境观察一周的业务指标确认无回归再推全量。整套流程下来我只把一个参数加到生产环境“内存和 IO 相关的参数只改 80% 的幅度留一点余量给内核自己判断”。比如vm.dirty_ratio建议值是 30我会先设 25 观察一段时间确认写延迟和吞吐都满足要求再微调到 30。最后说一个我自己的教训调优参数不是装完系统就一劳永逸的事业务模型变了参数就得跟着变。同一套参数在并发 1 万和并发 10 万的系统上表现可能完全相反。现在每季度我都会过一遍这些参数和当前业务的匹配度确认没有因为流量增长而悄悄变成新瓶颈。改参数永远要像做手术一样先备好回滚方案再下手。最稳妥的后悔药是sysctl -p之前先sysctl -a把当前值导出一份留着不然一段配置下去就很难说清改了什么。希望这些经验能帮你在调优的路上少踩几个坑。本文还有配套的精品资源点击获取