《Linux 系统参数与程序微观运行》总检索目录
硬核教程:从内核参数到程序微观运行,对话体 + 真实事故 + 迭代环 + 权衡表。 全书 27 章,纯汉字(含中文标点)口径约 30 万。每章「实战补遗/番外」为独立真实事故,可单独检索。
00-序与优化哲学.md — 第 00 章 序:只有懂微观,才配谈”优化”
- 0.1 “懂微观”到底懂的是什么
- 0.2 诊断循环:现象→推断→试错→观察→改进
- 0.3 “懂微观”不会让你变成算命的,但会让你少走弯路
- 0.4 一个必须提前破除的错觉:内核参数不是”性能开关”
- 0.5 本书的阅读约定
- 0.6 参数能解决什么,不能解决什么(先划清边界)
- 0.7 贯穿全书的六个真实现场(先睹为快)
- 0.8 一个把优化做成”负优化”的真实故事(序章收尾)
- 实战补遗一:
sysctl -w调好,重启却失效——加载顺序的坑 - 实战补遗二:把
echo 3 > drop_caches写进 cron 的”清内存”脚本,反而制造周期卡顿 - 实战补遗三:次”优化翻车”全过程——把 swappiness 调 0 反而 OOM
- 实战补遗四:观测优先于调参——从一款 APM 的”自我放大”翻车讲起
- 实战补遗五:实测驱动 vs 玄学调参——一张 A/B 对照表怎么读
- 实战补遗六:优化前先建基线——没有基线,所有”调好了”都是幻觉
01-全景地图.md — 第 01 章 两张地图:程序的微观旅程 & 系统参数家族
- 1.1 地图一:一个程序的微观旅程(总图)
- 1.2 地图一的补图:延迟都”藏”在哪几级
- 1.3 地图二:系统参数家族(/proc/sys 下都有谁)
- 1.4 “参数”不止 /proc/sys:还有这些兄弟
- 1.5 问题地图总表(现象 → 先怀疑哪级 + 先读哪个文件)
- 1.6 演化线小结(为什么参数是这样长出来的)
- 1.7 思考题
- 1.8 一个”慢”字背后,可能是这九级里的某一环
- 1.9 一张”怀疑清单”:卡顿时按这张表逐项排除
- 1.10 实战补遗:用”九级地图”反查一次跨机房慢请求
- 实战补遗一:把”九级地图”落成一张可勾选的排障 SOP(两个填表例子)
- 实战补遗二:第一次读 /proc,以及”被数字骗了”的那次
- 实战补遗三:级地图反查 SOP——一张能打印的”排查 checklist”
- 实战补遗四:次 curl 慢到 8 秒——用九级地图在 5 分钟钉到第 4 级
- 实战补遗五:用火焰图把”偶发卡顿”钉到某个 Go 闭包分配——on-CPU 火焰图的正确读法
02-从源码到进程.md — 第 02 章 从源码到进程:一个 hello 的诞生之旅
- 2.1 构建期:从人类文字到机器语言
- 2.2 ELF:磁盘上的”程序说明书”
- 2.3 加载期:
execve把”说明书”变成”活进程” - 2.4 运行期起跑:第一个 printf 发生了什么(预告)
- 2.5 这级和”系统参数”有什么瓜葛(承上启下)
- 2.6 演化线小结
- 2.7 思考题
- 2.5 静态链接 vs 动态链接:一个被忽视的运维炸弹
- 2.8 深度现场:一个被
-O2优化”吃掉”的并发可见性 bug——从 C 源码到机器码的断层 - 实战补遗一:文件描述符在
fork后”偷偷继承”,把连接池拖爆 - 实战补遗二:失控
fork把kernel.pid_max打满,新连接全EAGAIN - 实战补遗三:写时复制(COW)翻车——fork 之后内存”翻倍”的假象
- 实战补遗四:Go 的 goroutine 栈、mmap 与进程虚拟地址——为什么 top 里 RES 比你算的大
- 实战补遗五:fork 炸弹与 pid_max——僵尸进程把 PID 表占满的真实事故
03-虚拟内存与MMU.md — 第 03 章 虚拟内存与 MMU:进程眼里的”整片内存”是怎么骗出来的
- 3.1 为什么需要虚拟内存:一个”善意的谎言”
- 3.2 进程的虚拟地址空间布局
- 3.3 MMU 与多级页表:转换是怎么发生的
- 3.4 缺页中断:四种”兑现”的剧本
- 3.5 一次内存访问的延迟分解(把微观量化)
- 3.6 这级和 vm 参数的瓜葛(重点)
- 3.7 演化线小结
- 3.8 思考题
- 3.4 页表、TLB 与
vm参数的微观对应(预演) - 3.9 深度现场:
mmap与写时复制的两个真实账单 - 实战补遗一:
mmap大文件后,free里那块”说不清的内存” - 实战补遗二:
mmap之后文件被截断/删除,访问映射到SIGBUS而非SIGSEGV - 实战补遗三:TLB 与”缺页风暴”——大内存进程的隐形税
- 实战补遗四:TLB shootdown 与多核扩展——大页为什么能救延迟毛刺
- 实战补遗五:mmap SIGBUS 与 COW 翻倍——文件映射的两种”意想不到”
04-系统调用与内核态切换.md — 第 04 章 系统调用与内核态切换——那道看不见的鸿沟
- 一、先问一个”傻问题”
- 二、为什么要有这道墙?——特权级的设计意图
- 三、
write这一嗓子,到底喊了什么? - 四、过境要交多少税?——上下文切换的真实成本
- 五、参数穿插:控制”过境”行为的那些旋钮
- 六、真实事故:一个”CPU 明明不忙却慢得要死”的服务
- 七、把这章钉进你的脑子
- 🔧 思考题(带参考答案)
- 实战补遗一:io_uring 与”系统调用悬崖”——当 syscall 本身成了瓶颈
- 实战补遗二:vDSO 与 clock_gettime——为什么取时间”不走 syscall”;Go runtime 里 syscall 的真实边界
- 实战补遗三:read 返回 0 与 EOF 语义——Go 里”为什么我的循环读不到结尾”的真相
- 实战补遗四:次因 RLIMIT_NOFILE 没继承,凌晨 EMFILE 的事故
05-CPU调度器.md — 第 05 章 CPU 调度器——几千个人抢一根独木桥
- 一、先把问题问对
- 二、第一个机制:凭什么能把你拽下来?
- 三、CFS:用一个会计骗术解决”公平”
- 四、不止 CFS:实时调度类和它的危险
- 五、容器时代最坑的一个东西:CFS 配额与 Throttling
- 六、真实事故:凌晨的”CPU 不忙但接口超时”
- 七、参数小结:调度这一层的旋钮和它们的交易
- 八、这章的认知钉子
- 实战补遗一:CFS 的”公平”陷阱——低优先级任务饿死与 CPU 调度悬崖
- 实战补遗二:GOMAXPROCS 与 CPU 亲和性——把 Go 服务绑到特定核反而更慢的怪事
- 实战补遗三:CFS 调度周期与 RT 优先级——为什么一个实时任务能把整个核”据为己有”
- 🔧 思考题(带参考答案)
- 实战补遗四:CFS 调度把低延迟线程”饿”成高延迟
06-内存分配与回收.md — 第 06 章 内存分配与回收——一张永远在超发的空头合同
- 一、从一个荒谬的实验开始
- 二、为什么要 overcommit?——先理解设计动机
- 三、合同兑现的那一刻:从缺页到物理页
- 四、金库现金不够了:回收机制与水位线
- 五、Swap:被误解最深的机制
- 六、挤兑到来:OOM Killer 挑人的逻辑
- 七、脏页与写回:另一条延迟暗线
- 八、真实事故:一场三次推错的 OOM 连环杀
- 九、参数总表:
/proc/sys/vm的核心旋钮与它们的交易 - 十、这章的认知钉子
- 实战补遗一:伙伴系统与 slab 着色——内核态”内存分配”为什么也有碎片
- 实战补遗二:vmalloc 区耗尽与大块连续内存——为什么”空闲内存很多却分配失败”
- 🔧 思考题(带参考答案)
07-文件系统与PageCache.md — 第 07 章 文件系统与 Page Cache——世界上最伟大的一层谎言
- 一、一个让人不安的实验
- 二、page cache:整个系统最重要的一块内存
- 三、VFS:一层抽象伺候所有文件系统
- 四、撕掉谎言:
fsync和它的代价 - 五、Direct IO:主动放弃 page cache 的人
- 六、参数总表:文件系统这一层的旋钮
- 七、这章的认知钉子
- 实战补遗一:page cache 的”好心办坏事”——fadvise 用错与 drop_caches 自残
- 实战补遗二:O_DIRECT 与 buffered IO 的取舍——Go 里 io.Copy 为何有时比零拷贝慢一倍
- 实战补遗三:fadvise 正确姿势与双重缓存——page cache 和你的应用缓存重叠了
- 🔧 思考题(带参考答案)
08-块层与IO栈.md — 第 08 章 块层与 IO 栈——从一个 bio 到盘片上的磁畴
- 一、先建立一个物理直觉:磁盘为什么慢?
- 二、一个 IO 的完整下行路径
- 三、blk-mq:一场被 SSD 逼出来的重写
- 四、IO 调度器:三个在赌不同东西的赌徒
- 五、把
iostat彻底讲清——一半人读错的地方 - 六、队列深度与相关参数
- 七、真实事故:一个”换了 NVMe 却没变快”的数据库
- 八、参数总表:块层的旋钮
- 九、这章的认知钉子
- 实战补遗一:IO 调度器选错——mq-deadline 反而比 none 慢的怪事
- 实战补遗二:SSD 写放大与 fio 真实延迟测法——别被 iops 数字骗了
- 实战补遗三:IO 调度器 none 与 mq-deadline 的取舍——多队列下软件队列深度怎么调
- 🔧 思考题(带参考答案)
09-中断软中断与驱动.md — 第 09 章 中断、软中断与驱动——一个无法回避的两难
- 一、先想清楚这个两难
- 二、第一层解法:上半部与下半部
- 三、NAPI:轮询和中断的联姻
- 四、核心实战问题:为什么只有一个核在忙?
- 五、真实事故:32 核的机器,吞吐卡在 40 万 PPS
- 六、参数总表:中断与软中断层
- 七、这章的认知钉子
- 实战补遗一:软中断风暴——ksoftirqd 跑满 100% 的”看不见的 CPU 税”
- 实战补遗二:IRQ 亲和性 smp_affinity 与 RPS/RFS——把网卡中断绑到对的核
- 实战补遗三:workqueue 与 kworker——为什么你的”内核任务”跑在某个 kworker 线程、还绑在特定核
- 🔧 思考题(带参考答案)
10-网络栈微观全景.md — 第 10 章 网络栈微观全景——一个数据包怎么爬进你的 socket
- 一、先把整条路铺开:一个数据包的 IP/TCP 旅程
- 二、三次握手为什么是三次——它不是仪式,是两次”确认活着”
- 三、syn 队列与 accept 队列:连接建立的”两道门”
- 四、数据怎么流:发送缓冲区、窗口、Nagle、延迟确认
- 五、拥塞控制:它本质上在赌
- 六、TIME_WAIT:为什么让人恨,又为什么不能删
- 七、缓冲区与 bufferbloat:tcp_rmem / tcp_wmem / tcp_mem
- 八、重传与保活:连上了不代表永远在
- 九、事故一:半夜网关拒绝新连接
- 十、事故二:重传率 5%,找了一周
- 十一、net.ipv4.tcp_* 参数总表(拿什么换什么)
- 十二、🔧 思考题(都配参考答案)
- 实战补遗一:NAPI 与 GRO 的”收包魔法”——为何小包吞吐反而掉
- 实战补遗二:零拷贝 sendfile/splice 与 TSO/GSO——Go 的 io.Copy 为何慢;分段 offload 的隐形红利
- 实战补遗三:半连接队列 SYN backlog 与 syn flood——新连接上不去,未必是全连接队列的锅
- 实战补遗四:用
ss+tcpdump还原一次”建连慢”的真实链路
11-全链路综合故事.md — 第 11 章 全链路综合故事——一次点击,30 秒里的微观全景
- 一、先立一个铁规矩:链路是分段的,故障也分段
- 二、一条完整时间线:从手指到刷新
- 三、把”卡 2 秒”拆开:一张决策树
- 四、一个综合事故的完整迭代环(把前面全用上)
- 五、回到最初的问题:程序到底”经过什么”
- 六、🔧 思考题(都配参考答案)
- 实战补遗一:个 POST 写请求从网卡到磁盘的”延迟账本”
- 实战补遗二:次”间歇式 2 秒超时”的全链路账本归类
- 实战补遗三:次”读多写少”查询变慢,用全链路账本归到 page cache 命中率
- 实战补遗四:次跨机房慢请求的”九级反查”实战
- 实战补遗五:写放大跨层追踪——应用写 1KB,落盘 100KB 的”幽灵账单”
- 实战补遗六:gRPC 超时连锁与重试风暴——一个 1s 超时如何把下游打挂
- 实战补遗七:缓存击穿与热点 key——一个爆款把数据库打挂的全链路透视
- 七、卡 2 秒的分段决策树(文字版 + 检索)
12-proc-sys-vm总地图.md — 第 12 章 /proc/sys/vm 总地图——内存这颗炸弹的引信清单
- 一、先建分类地图:别把”安全阀”当”日常旋钮”
- 二、overcommit 三兄弟:malloc 的”空头合同”由谁担保
- 三、水位线三件套:内核什么时候开始”慌”
- 四、脏页四件套:写的”谎言”什么时候被揭穿
- 五、swap 与回收倾向:脏数据 vs 干净缓存谁先死
- 六、OOM 与 compact:被杀的规矩、碎片的整理
- 七、drop_caches 与保留:正经用法 vs 作死
- 八、
/proc/sys/vm总表(拿什么换什么) - 九、🔧 思考题(都配参考答案)
- 十、vm 参数的联动效应(别孤立调一个)
- 十一、vm 调参决策树:拿到一台新机器先问什么
- 十二、
sysctl的”假生效”:你以为改了,其实被 tuned / 启动顺序 / 容器权限覆盖了 - 实战补遗一:给你的服务画一张
vm画像——四类负载对应四组参数 - 实战补遗二:
vm默认值陷阱速查——哪些默认值是给桌面/通用设的,生产该改 - 实战补遗三:把一行 vmstat 读”活”——用真实数字走一遍
- 实战补遗四:改了 sysctl 没生效——字母序加载与”后写的覆盖先写的”
- 实战补遗五:THP 与 Go GC 的恩怨——madvise 还是 never;dirty 回写怎么监控才不踩
- 实战补遗六:脏页观测 nr_dirty 与早期预警——在被前台写阻塞前就看见
13-vm场景化用法.md — 第 13 章 vm 场景化用法——你的负载长什么样,参数就怎么配
- 一、先立一个总纲:没有”最优”,只有”匹配你的画像”
- 二、画像 A:数据库 / 缓存服务
- 三、画像 B:文件服务器 / 高吞吐写
- 四、画像 C:低延迟交易 / 实时
- 五、画像 D:容器 / 云原生(混部多租户)
- 六、画像 E:NUMA 大内存(256G+ 单机)
- 七、一个场景调参的完整迭代环(画像 A 实战)
- 八、🔧 思考题(都配参考答案)
- 九、常见负载的参数冲突与架构化解
- 十、监控 vm 的正确姿势(看哪些计数器)
- 十一、监控告警误报:把 page cache 当”内存泄漏”——告警风暴淹没有问题
- 实战补遗一:脏页节奏与 swappiness 联动推错,Kafka 消费 lag 雪崩
- 实战补遗二:内存密集服务的
vm组合拳——以 Redis 类缓存为例走一遍 - 实战补遗三:网络密集服务的
vm—以 Envoy/Nginx 网关为例走一遍 - 实战补遗四:Go 程序员的专属坑——THP 与 GC 的”暗中作对”
- 实战补遗五:容器里改 vm 参数”看不到效果”——因为那是宿主的旋钮
- 实战补遗六:套 vm 模板——数据库 / 缓存 / 消息队列该分别怎么设
14-vm调优实战案例.md — 第 14 章 vm 调优实战案例——四个把人坑哭的真实故障
- 事故一:
overcommit_memory=2把服务卡得起不来 - 事故二:
swappiness=0反而让延迟更抖 - 事故三:
min_free_kbytes太小,连网卡都丢包 - 事故四:
drop_caches定时脚本把 I/O 打爆 - 五、🔧 思考题(都配参考答案)
- 六、第五个实战:THP 透明大页引发的延迟抖动
- 七、第六个实战:
vm.panic_on_oom=1把一次可救的 OOM 变成整机重启 - 八、第七个实战:
watermark_scale_factor=10在大内存上引发 direct reclaim 周期性雪崩 - 实战补遗一:
admin_reserve_kbytes/user_reserve_kbytes——OOM 时把你挡在门外的”隐形门槛” - 实战补遗二:
oom_kill_allocating_task=1用反——杀的是”正在分配的”,不是”最胖的” - 实战补遗三:脏页触顶,前台进程被”拖下水”同步写盘
- 实战补遗四:dirty_background_ratio 与 writeback 的”暗流”——吞吐型服务的隐形天花板
- 实战补遗五:vfs_cache_pressure 调错——dentry 回收过度导致 stat 变慢
- 实战补遗六:K8s 里 Pod OOM 但节点还有内存——cgroup 限额与 vm 的错位
15-net家族参数分类.md — 第 15 章 net 家族参数分类——协议栈各层的守门人
- 一、先画
net的分层地图 - 二、
net.core:通用收发管道(所有协议共享) - 三、
net.ipv4:IP 层 + TCP(非 tcp 部分) - 四、
net.ipv6:IPv6 特有守门人 - 五、
net.unix与net.bridge:常被忽略的两支 - 六、
net家族总表(守门人速查) - 七、🔧 思考题(都配参考答案)
- 八、net 参数的”天花板”联动陷阱
- 九、net 故障速查:症状 → 参数
- 十、net 实战事故:
rp_filter=1把跨国专线的回包全丢了 - 十一、net 实战事故二:
net.core.rmem_max天花板把 BBR 长肥管道吞吐卡死 - 实战补遗一:
net.core.somaxconn+tcp_max_syn_backlog——突发流量下,新连接被”静默丢弃” - 实战补遗二:
nf_conntrack_max耗尽,新连接被静默 DROP——你调的sysctl不在这个家族 - 实战补遗三:两个队列都满了,连接却”静默消失”
- 实战补遗四:rp_filter 反向路径过滤——“能 ping 通却建不了连接”的幽灵
- 实战补遗五:tcp_abort_on_overflow 的”告警价值”——把静默丢变成显性报错
- 实战补遗六:tcp_tw_reuse 与 TIME_WAIT 洪水——高并发短连接怎么不被端口耗尽卡死
16-fs与kernel参数.md — 第 16 章 fs 与 kernel 家族——文件句柄、进程号、崩溃开关
- 一、
fs家族:全系统的”打开了多少文件” - 二、
kernel家族:进程号、线程、信号量、崩溃开关 - 三、
fs与kernel总表(守门人速查) - 四、两个真实事故的迭代环(简版)
- 五、🔧 思考题(都配参考答案)
- 六、fs 与 kernel 的真实事故三则(补完本家族)
- 七、第四则事故:磁盘没满却建不了文件——inode 耗尽
- 八、第五则事故:
kernel.threads-max触顶,高并发网关新连接线程起不来 - 实战补遗一:
fs.inotify.max_user_watches——监控 agent 把整台机器”看”崩了 - 实战补遗二:
kernel.sem四个值配错——System V 信号量把批量导入卡死 - 实战补遗三:pid_max 被僵尸占满,新进程起不来
- 实战补遗四:kernel.sem 四值——被 ENOSPC 误导的信号量配额
- 实战补遗五:fs.inotify.max_user_watches 耗尽——“too many open files”的表亲陷阱
- 实战补遗六:fs.file-max、aio-max-nr 与 Docker 默认 ulimit——“Too many open files” 到底卡在哪一层
17-其他家族与cgroup-ulimit对照.md — 第 17 章 其他家族与”长得像 sysctl 的近亲”对照
- 一、其他小家族扫尾(知道它们守什么门即可)
- 二、最大的混淆源:
/proc/sysvs/sysvsulimit - 三、
ulimit:进程级限制(不是 sysctl!) - 四、
/sys/fs/cgroup:分组资源限制(容器就是它) - 五、sysctl 与近亲对照总表(找对门)
- 六、🔧 思考题(都配参考答案)
- 七、sysctl / /sys / ulimit 三世界实战:一个限制该去哪改
- 八、cgroup v1 vs v2 关键差异速查
- 九、真实事故:在 sysctl 里调了一周容器内存,其实该改 cgroup
- 十、真实事故二:想限磁盘 IO,在
sysctl里翻半天——其实该改/sys/block队列或 cgroupio.max - 实战补遗一:cgroup v2
cpu.max硬配额——把 Redis/etcd 的”后台活”误伤下线 - 实战补遗二:cgroup v2
memory.lowvsmemory.min——把”保命的”和”该保的”搞混 - 实战补遗三:ulimit -n、fs.file-max、cgroup 三套”文件描述符账本”
- 实战补遗四:cpu.weight 与 cpu.max——“相对让”与”绝对砍”的两条节流线
- 实战补遗五:memory.events 监控实战——把 cgroup OOM 接进告警
- 实战补遗六:oom_group 连坐与 memory.stat——cgroup v2 里”杀一个还是杀一组”
18-神秘卡顿.md — 第 18 章 神秘卡顿——“全机冻结几秒”的微观真凶
- 一、卡顿有两种脸:你的慢 vs 内核的”暂停”
- 二、事故全景:订单服务的”幽灵卡顿”
- 三、配套参数与观测:怎么”看见”内核的暂停
- 四、参数总表(这一章动过的”拿什么换什么”)
- 五、🔧 思考题(都配参考答案)
- 六、第二个现场:soft lockup 导致的整机冻结(暂停类另一兄弟)
- 七、内核”暂停类”五兄弟总账(把本章升级成武器)
- 八、第三个现场:写回与 journal 拥堵,把”写”冻住(暂停类第四兄弟)
- 实战补遗一:khugepaged 后台合并大页,把延迟毛刺做成”周期性 200ms”
- 实战补遗二:soft lockup 真凶——一个内核模块持自旋锁太久,把单核冻 20 秒
- 实战补遗三:RCU stall——比 soft lockup 更隐蔽的”内核假死”
- 实战补遗四:watchdog_thresh 与 softlockup_panic——“卡多久算死”的取舍
- 实战补遗五:RCU stall 与 soft lockup 误报——内核”卡住”不一定是应用慢
19-OOM连环杀.md — 第 19 章 OOM 连环杀——“一个接一个被杀”的雪崩现场
- 一、OOM Killer 的杀人逻辑:它到底杀谁
- 二、事故全景:容器集群的”凌晨连环杀”
- 三、配套参数:四个角色在”谁死”上的分工
- 四、参数总表(这一章动过的”拿什么换什么”)
- 五、🔧 思考题(都配参考答案)
- 六、第二个现场:cgroup 内存上限误设,触发”组内连环 OOM”
- 七、OOM 排查的”十条肌肉记忆”
- 八、第三个现场:memory.high 软上限被当硬上限,引来”节流风暴”而非 OOM
- 实战补遗一:oom_score_adj 配反,把数据库杀了、留着泄漏进程
- 实战补遗二:cgroup v2
memory.max设太紧,流量高峰就 OOM 且连环杀 - 实战补遗三:oom_score_adj 战略——保核心、杀边缘,而不是杀最胖的
- 实战补遗四:cgroup OOM 与节点 OOM——两套杀手,规则不同
- 实战补遗五:PSI 早期预警与 systemd OOMPolicy——在被杀之前先知道、被杀之后怎么收
20-磁盘IO毛刺.md — 第 20 章 磁盘 I/O 毛刺——“盘没忙,却要等几百毫秒”的骗局
- 一、I/O 毛刺的脸:
await高而%util低的矛盾 - 二、事故全景:支付服务的”50ms 毛刺”
- 三、配套参数:块层你能拧的旋钮
- 四、参数总表(这一章动过的”拿什么换什么”)
- 五、🔧 思考题(都配参考答案)
- 六、第二个现场:云盘”突发 IOPS 配额”导致的周期性卡顿
- 七、IO 排障的总账(把第 8、20 章收成武器)
- 八、第三个现场:中断没绑核、RPS 没开,单 CPU 软中断成 IO 瓶颈
- 实战补遗一:
/sys/block队列参数与 IO 调度器选错,把 NVMe 搞慢 - 实战补遗二:
/sys/block的wbt_lat(写回节流)把 NVMe 写吞吐限死 - 实战补遗三:read_ahead_kb 误配——顺序读变”小碎读”的毛刺
- 实战补遗四:SSD 写放大与 NVMe 多队列——“我只写了 1KB,凭什么盘忙成这样”
- 实战补遗五:fstrim 与 wbt_lat——SSD 回收和写回节流两道不同的阀门
21-网络重传与TCP调优.md — 第 21 章 网络重传与 TCP 调优——“建不上连”和”找了一周的重传”
- 一、先认两张脸:连接建不上 vs 数据传得慢
- 二、事故 A:高并发短连接,新连接建不上
- 三、事故 B:重传率 5%,找了一周
- 四、配套参数:这两类故障涉及的
tcp_* - 五、参数总表(这一章动过的”拿什么换什么”)
- 六、🔧 思考题(都配参考答案)
- 七、第二个现场:连接池耗尽引发的”建连超时雪崩”
- 八、网络排障总账(把第 10、21 章收成武器)
- 九、第三个现场:客户端 ephemeral 端口耗尽,EADDRNOTAVAIL 建连失败
- 实战补遗一:
tcp_retries2默认 15 次,把”故障后端”挂成 15 分钟的僵尸 - 实战补遗二:
tcp_mtu_probing解开”MTU 黑洞”:大包静默丢,连接能建但传不动 - 实战补遗三:tcp_retries2 与”假死连接”——应用层以为连着,内核早放弃了
- 实战补遗四:TCP 窗口收缩——rwnd 满导致的”吞吐塌方”
- 实战补遗五:tcp_window_scaling 与 BBR——长肥管道(LFN)里默认 Reno 为何跑不满带宽
22-内存泄漏vs缓存挤压.md — 第 22 章 内存泄漏 vs 缓存挤压——“free 很低”到底是不是泄漏
- 一、先拆
free:三态误读是万恶之源 - 二、事故全景:“内存 95%“的假警报
- 三、配套:PSI——内核在喊”我扛不住了”
- 四、参数与观测总表(这一章涉及的”看什么 / 调什么”)
- 五、🔧 思考题(都配参考答案)
- 六、第二个现场:透明大页(THP)的”内部碎片”假占用
- 七、内存排障总账(把第 6、12、22 章收成武器)
- 八、第三个现场:slab(dentry/inode)缓存暴涨,vfs_cache_pressure 压不下来
- 实战补遗一:
skbuff_head_cache/TCPslab 暴涨——网络侧的”假泄漏”,drop_caches救不了 - 实战补遗二:PSI 的
full与some误读——把”即将 OOM”当成”只是有点忙” - 实战补遗三:
/proc/<pid>/smaps定位”哪段地址空间在涨”——一个mmap文件没munmap的缓慢泄漏 - 实战补遗四:SReclaimable 与 SUnreclaim——你能回收的,和 drop_caches 救不了的
- 实战补遗五:误把 page cache 当泄漏——一场”内存泄漏”告警乌龙
- 实战补遗六:Go pprof heap 与 RSS 对不上——为什么”堆才 400M,RES 却 1.2G”
23-NUMA与大页.md — 第 23 章 NUMA 与大页——大内存机器上最隐蔽的两类故障
- 一、NUMA 的脸:内存也有”远近”
- 二、事故 A:NUMA 机器上的周期性延迟毛刺
- 三、事故 B:大页(THP)在数据库上”鲸吞 + 冻进程”
- 四、参数总表(这一章动过的”拿什么换什么”)
- 五、🔧 思考题(都配参考答案)
- 六、第二个现场:NUMA 绑核不当,一半 CPU 饿死
- 七、大内存机器调参总账(把第 23 章收成武器)
- 八、第三个现场:显式 HugeTLB 预留吞掉普通内存,反而引发 OOM
- 实战补遗一:
zone_reclaim_mode=1与numactl --interleave——NUMA 上的两个”好心办坏事” - 实战补遗二:
numactl --membind绑错 node——核与内存不同 node 的”远内存”陷阱 - 实战补遗三:容器里调
zone_reclaim_mode想优化 NUMA,其实是找错门 - 实战补遗四:NUMA 绑核 + 网卡中断亲和——“内存近、中断也近”才真快
- 实战补遗五:THP defrag 的”分配阻塞”——开 THP 后 malloc 偶发卡
- 实战补遗六:K8s topologyManager 与跨 node 内存带宽——绑核绑内存别只绑一半
24-优化哲学.md — 第 24 章 优化哲学——把全书的”母题”提炼成可复用的思维模型
- 一、铁律一:懂微观,才配谈优化
- 二、母题一:平均值掩盖分布
- 三、母题二:缓冲区治突发,不治过载
- 四、母题三:通用机制 + 专家逃生口
- 五、母题四:规模逼出结构
- 六、母题五:成本假设反转,优化变负担
- 七、母题六:诊断铁律——先定位,再调参
- 八、benchmark 的七大陷阱
- 九、参数不是开关,是权衡(总账)
- 十、🔧 思考题(都配参考答案)
- 实战补遗一:两次优化,一次封神一次翻车
- 实战补遗二:“先量化再优化”——把火焰图当摆设、凭感觉调了一周的反面教材
- 实战补遗三:可观测性优先于调优——一套”优化前先看灯”的文化
- 实战补遗四:先测量后优化——perf stat 五个关键计数器别只看 CPI
25-工具箱.md — 第 25 章 工具箱——下次故障,你该抡哪把扳手
- 一、先建”工具分层地图”
- 二、四把瑞士军刀(必精通)
- 三、进阶核武器(前四把指不出方向时才上)
- 四、专项工具(按子系统)
- 五、网络专项(
tcpdump/ethtool/nstat) - 六、症状→工具 对照总表(速查)
- 七、🔧 思考题(都配参考答案)
- 八、实战:用工具箱把一次”玄学卡顿”讲到根上
- 实战补遗一:用 bpftrace 把”到底卡在内核哪一层”钉死
- 实战补遗二:把零依赖刀收窄后,用 perf 火焰图一锤定音
- 实战补遗三:
sar的隐藏字段——90% 人只看%util,漏掉真正报警的那些 - 实战补遗四:
offcputime(bpftrace)—定位”卡在等锁/等 IO”的离线时间 - 实战补遗五:bpftrace 一行脚本——不重启、不插桩看内核
- 实战补遗六:biolatency / biosnoop——把块层延迟分布”看见”
- 实战补遗七:eBPF 入门——写第一个 kprobe 抓函数耗时,比 perf 更精准
26-结语.md — 第 26 章 结语——一张地图,和你真正开始独立排障的起点
- 一、一张地图:程序从源码到硬件
- 二、检索表:遇事查哪章
- 三、“懂微观”的长期意义
- 四、给老哥的”后续自修路线”
- 五、全书的”一句话总纲”
- 六、🔧 思考题(都配参考答案)
- 七、遇事查哪章:一张检索表(把 26 章变成你的工具书)
- 八、写在最后
- 番外一:墨叔的私房话:从”会调参”到”懂机制”到”能造工具”
- 番外二:墨叔的”三级跳”——从”会调参”到”能造工具”
- 番外三:把全书 26 章收成一张”参数→哪一级→哪个文件→哪个计数”总检索脑图
- 番外四:给 Go 程序员的一张”内核参数速查卡”
- 番外五:20 道自测题——检验你是否真懂,而非”记住了”
- 番外六:张 Linux 微观运行速查卡——参数 → 现象 → 工具 三列对照
按主题速查(现象 → 章节)
- 内存回收 / OOM / cgroup:第 6、12、13、14、17、19、22 章,及第 0/24 章哲学
- vm 参数场景化:第 12、13、14 章实战补遗
- 网络栈 / TCP 调优:第 10、15、21 章,第 1 章九级地图
- 磁盘 IO / 块层:第 7、8、20 章
- CPU 调度 / 中断:第 5、9 章
- NUMA / 大页 / THP:第 3、23 章
- 进程 / 虚拟内存 / 系统调用:第 2、3、4 章
- 全链路排障:第 1、11 章
- 工具箱(perf / eBPF / bpftrace):第 25 章
- 容器 / K8s 里的误区:第 14、17、22、23 章实战补遗