CAS 和 MGLRU 进入 Linux 7.2——Linux 调度器的 cache 盲区与 LRU 的冷热误判,困扰数据库工作负载几十年
MGLRU 改进让 MongoDB 吞吐量上升 30 到 100%;Cache Aware Scheduling 的扩展补丁让 MySQL 基准测试提升了 360%。两项工作在同一个 Linux 7.2 合并窗口期间落地,但数字差了一个数量级。这个差距值得解释:两个数字背后是结构上完全不同的受益路径,各自指向 Linux 调度器和内存管理在数据库场景下积累已久的盲区。
调度器把 CPU 核当可替换工人,但 buffer pool 要的是邻居
Linux CFS 做负载均衡的基本假设是:任务可以被自由地分配到最空闲的核。这个假设在大多数独立任务上合理,在数据库 workload 上有一个系统性漏洞——它对 cache 拓扑是盲目的。
现代多路服务器的 LLC(Last Level Cache)不是全局共享的:同一 LLC 域内的核之间共享缓存,跨域访问要经过内部互联,延迟高出数倍。MySQL InnoDB 的 buffer pool 是一个高竞争的共享数据结构,多个工作线程同时读 B+ 树节点、更新页状态、修改内部 LRU 链表,每秒产生数以百万计的 cache line 读写。如果持有同一 buffer pool 段的两个线程被"均衡"分配到不同 LLC 域的核上,每次 cache line 传递都需要穿越互联,变成一次 LLC miss。并发越高,被迫跨域的线程越多,惩罚越严重,且呈超线性增长——这是一个随 TPS 放大的税,不是固定开销。
Cache Aware Scheduling 的基础版本在 Linux 7.2 合并窗口期间进入内核,引入了 LLC-centric 任务聚合,让共享数据的线程倾向于调度到同一 LLC 域。基础版本有一个局限:它只处理能被单个 LLC 域容纳的 workload,当任务规模跨越多个 LLC 域时聚合失效。6 月 25 日,海光(Hygon)工程师向内核邮件列表提交了扩展补丁,把静态的 LLC-centric 聚合升级为层次化、动态扩缩的拓扑感知——调度域根据实际 workload 规模在不同拓扑层级之间动态切换。基于这套扩展补丁的测试结果:Hackbench 提升 49%,Schbench 提升 20%,MySQL 提升 360%。
海光主导这个补丁的动因直接:其 x86 兼容处理器在国内数据中心大量部署,本身具有复杂的多 die NUMA 拓扑——正是基础版 CAS 最难处理的场景。这套扩展补丁截至 6 月 25 日仍在审查阶段,尚未合并进 7.2 主线;360% 是对建议补丁的测试结果,不是对已发布内核的测量值。
active/inactive 双链表无法区分扫描噪音和真正热页
MongoDB 的 WiredTiger 存储引擎有自己的内部缓存,同时依赖操作系统 page cache 缓存压缩后的数据文件。内存回收策略的好坏,直接影响 page cache 中能保留多少热数据。
传统 Linux active/inactive 双链表对冷热的判断是二元的:任何一次访问都能把一个页面提升到 active 链表。全表扫描或索引重建会把大量"只访问一次"的冷页灌进 active 链,把长期频繁访问的热数据页推进 inactive,在内存压力下优先驱逐。下次访问热数据时触发页错误,重新从磁盘加载,出现延迟尖刺。双链表将所有访问一视同仁——"一分钟前偶尔扫到一次"和"过去一小时每秒命中 500 次"得到相同权重。
MGLRU 用多个时间"代"(generation)跟踪页面的访问历史:只扫描一次的页面落在最老代,持续高频访问的页面留在最新代。内存压力下驱逐最老代,热数据获得实质保护。这个改进与 WiredTiger 的存储模型高度匹配——WiredTiger 依赖 OS page cache 作为压缩数据的二级缓存,而 MGLRU 正好提升了 OS 这层的页面判断精度。
MongoDB 30 到 100% 的区间取决于存储 I/O 速度,不是测试误差:下限(30%)出现在 NVMe 等快速存储场景,上限(100%)出现在慢速 I/O 场景。MGLRU 的收益机制是减少热页被误驱逐后重新从磁盘读取的次数,I/O 越慢,每次被避免的页错误节省的时间就越多,收益因此随存储延迟放大。MGLRU 改进已进入 Linux 7.2 合并窗口,是这次两个特性里更确定能在 7.2 正式版中使用的一个。
超线性惩罚 vs. I/O 上限:倍率差是机制决定的,不是随机的
360% 和 30-100% 的量级差,来自两个优化机制各自的放大特征。CAS 消除的是超线性增长的惩罚项。N 个线程争同一 buffer pool 段时,跨 LLC 域的 cache coherence 流量近似 N² 级别;CAS 收拢线程后,消除的是这个平方项,而不只是 N 条 cache miss。这解释了为什么高并发场景的提升幅度远超线性预期。
MGLRU 消除的损耗受 I/O 子系统速度约束。被错误驱逐的热页每次重新读取需要完成一次磁盘 I/O,节省的时间以单次 I/O 延迟为单位累加。即使完全消除误驱逐,上限是把所有本该避免的 I/O 省掉——这是一个有界的收益空间,不存在超线性放大。
MySQL InnoDB 用自己管理的 buffer pool,所有数据 I/O 先经过这个共享结构,多线程竞争高度集中,CAS 的 LLC 感知直接命中最激烈的争用路径。MongoDB WiredTiger 通过内部缓存 + OS page cache 双层架构管理内存,CPU 层的 cache coherence 竞争相对分散,对 CAS 的依赖没有 InnoDB 那么直接。
CAS 减少 cache miss,也间接降低了 MGLRU 的 page 驱逐压力——CPU 触发的内存总线访问减少,需要被驱逐并重新加载的 page 随之减少。两者同时生效时,收益不是简单叠加。
哪类 workload 能复现收益,何时能用到
CAS 的受益前提:多核多 LLC 域服务器(8 核以上的多路机器,4 核以下拓扑过于简单),高并发 OLTP 场景(TPS 在 buffer pool 饱和点以上),且 buffer pool sharding 数量适中——过度 sharding 已经部分缓解了 cache line 竞争,会压低 CAS 的边际收益。单实例低并发的 MySQL 实例基本感受不到变化。
MGLRU 的受益前提:MongoDB 使用 WiredTiger(默认),内存略小于活跃工作集大小(内存充裕时热页不会被驱逐,改进效果不明显),工作负载中混有扫描类操作(全表扫描、聚合、索引重建)。纯点查询场景下的收益有限。MySQL 8.0 默认使用 InnoDB 自管理 buffer pool,受 MGLRU 影响较小,但依赖 OS page cache 的第三方存储引擎或 MySQL MyISAM 遗留场景会有收益。
时间线上,Linux 7.2 合并窗口 6 月底关闭,MGLRU 改进已在主线,相对稳定,值得尽早在测试环境验证;CAS 扩展补丁(360% MySQL,来自海光,lore.kernel.org/lkml/20260625030759.25928-1-wujianyong@hygon.cn/)可以手动应用到当前内核树进行评估,待后续合并后再考虑生产部署。Linux 7.2 不是 LTS,依赖托管实例的团队距离生产可用还有相当一段路。