第 3 篇 说明 Cache 按 clean/dirty 计量,且 dirty 页不能直接释放。把页真正赶出 cache 的子系统是 Eviction。Architecture Guide Eviction 把目标说死:把 cache 维持在用户设定的总量与 dirty 上限内;一旦超过 target,就触发驱逐把用量压回去。
本文钉住:线程与队列结构、clean vs dirty eviction、target/trigger 旋钮、以及「应用线程被迫做驱逐」的条件。Reconciliation 与 HS 写入的细节分别在第 6、8 篇;本篇只钉 契约:dirty eviction ⇒ reconcile ⇒ 最新进用户表、旧版进 History Store。
本文是「WiredTiger 内核」系列第 4 篇(共 17 篇)。→ 系列目录
先修:第 3 篇。续读:第 5–6 篇(update chain / Reconciliation);第 08 篇 History Store。
版本锚定:Architecture Guide Version 12.0.0 /
developEviction;源码mongodb-8.0的src/evict/。结构名以 Guide 表为准(WT_EVICT、队列条目等);Guide 不与发版锁步。
一、目标与组件
Eviction 由以下部分组成(Eviction):
| 组件 | 职责 |
|---|---|
| Eviction server(1) | 遍历各树,找可驱逐候选;近似 LRU 排序后把较旧的一批推进队列 |
| Worker threads(0…N) | 从队列取页并执行驱逐;数量可在配置的 min/max 间动态伸缩 |
| Queues(3) | 两条普通队列 + 一条 urgent 队列 |
Server 在树与树之间尽量公平,并记住每棵树上次走到的位置。候选按最近访问时间排序后,取大约 三分之一最旧 的可驱逐页入队——Guide 称之为近似 LRU。
Worker 通过条件变量与 server 协作:等队列有活,再独立驱逐直到队列空。也可以配置为只有 server、没有 worker:此时 server 自己找页并驱逐。
flowchart LR
srv["Eviction server<br/>walk trees approx LRU"] --> q["Ordinary queues"]
srv --> uq["Urgent queue"]
q --> wk["Worker threads"]
uq --> wk
wk --> clean["Clean: free memory"]
wk --> dirty["Dirty: reconcile then write"]
app["App thread under pressure"] --> dirty
二、Clean vs dirty eviction
Guide 定义与第 3 篇一致,驱逐路径分叉:
| 类型 | 条件 | 行为 |
|---|---|---|
| Clean eviction | 页无脏内容 | 直接从内存移除;磁盘页不变 |
| Dirty eviction | 页已修改 | 走 reconciliation:丢掉过时内容;最新值进 data store(用户表);更旧值进 History Store |
这是本系列主线最硬的一句工程契约,也是 第 08 篇 「用户表只留最新、旧版旁路」在 eviction 路径上的落点。Checkpoint 路径同样 reconcile 脏页,但动机是持久化一致快照(第 9 篇);Eviction 的动机是 腾 cache。
独占与读者
若仍有线程在读该页内容,页不能被驱逐;server/worker 在确认可驱逐后必须锁定并取得排他访问,避免检查通过后并行读者再进入。
Urgent 队列
强制驱逐标记的页进入 urgent 队列(在下列条件满足时;否则可由应用线程自行驱逐该页):
- 操作禁用了 eviction 或 splitting;或
- session 阻止 reconcile。
Urgent 队列优先于普通队列。
三、Target 与 Trigger
可在 wiredtiger_open 或
WT_CONNECTION::reconfigure
配置。对每一对指标:target 必须低于对应
trigger。
| 配置项 | 含义(Guide) |
|---|---|
eviction_target |
总体 cache 用量目标(占 cache 百分比);达到后 worker 积极驱逐 |
eviction_trigger |
总体用量触发线;达到后应用线程开始参与驱逐 |
eviction_dirty_target /
eviction_dirty_trigger |
同上,但只针对 dirty 占比;dirty 达 dirty_trigger 时应用线程会被节流并做驱逐 |
eviction_updates_target /
eviction_updates_trigger |
针对 cache 中 updates 字节量;达 trigger 时应用线程参与 |
「任何自读入磁盘后被修改过的页」都算 dirty。
应用线程协助驱逐
当工作负载写入速度超过 eviction 清理速度、cache
压不下来时,应用线程在继续读/写之前会被要求先完成部分 worker
同类工作。这是正确性/稳定性机制,不是可选优化——表现为延迟尖刺时,应同时看
dirty 比例与 eviction 统计(第 15 篇),而不是只加
cacheSizeGB。
MongoDB 把部分旋钮映射到存储引擎参数;具体名以手册为准,机制以本表为准。
四、与 Checkpoint 的衔接(预告)
Checkpoint 章:在 checkpoint 事务开始(pin 住内容)之前,会先借 eviction 把 dirty 压到目标比例,以利用多线程 eviction、缩短 checkpoint 临界区;checkpoint 线程会等待,除非看不到进展。
含义:eviction 不只是「内存满了才跑」的后台 GC,也是 checkpoint 的前置减压阀。第 9 篇展开顺序:锁 → eviction 减压 → prepare → 用户表 → HS → flush → 元数据。
五、HS eviction 与用户表 eviction
Guide Eviction 在 dirty 路径上写明旧版本进 History Store;History Store 自身的页也会占用同一 cache,并参与驱逐。第 08 篇开放问题 3 问的正是:历史页与用户热页抢同一池时,主路径是否可变慢。本篇只钉机制入口:
- 用户表 dirty eviction → reconcile → 可能写入 HS(增加 HS 脏页/内容);
- HS 页随后也需被 reconcile/evict,才能让 cache 真正降下来。
没有本站实测前,不写「HS 占比 X% 即异常」之类阈值。
六、争论、间隙与开放问题
争论(有 Guide 依据): 应用线程参与 eviction 保证 cache 有界,但把延迟尖刺推到前台请求。调高 cache 或放宽 dirty_trigger 只是推迟矛盾,不取消「脏页必须 reconcile」的成本。
工程间隙: Guide 结构名与
mongodb-8.0
头文件可能局部重命名(例如队列条目类型前缀);排障以源码
src/evict/ 与 MongoDB 所带版本为准。本篇无
serverStatus / WT statistics 实测。
开放问题:
- 在更新密集 + 大 HS 窗口下,dirty_trigger 与 updates_trigger 谁先打满更常见?(需实验台账)
- HS 与用户表的 eviction 公平性阈值(第 08、15 篇)。
七、收束
- Eviction = server 近似 LRU 选页 + worker(或高压下的应用线程)执行。
- Clean 直接释放;dirty 必须 reconcile,最新进用户表、旧版进 HS。
- target/trigger(总量、dirty、updates)决定后台忙还是前台协助。
下一篇进入页上写路径:B-Tree 与 update
chain——eviction/reconcile 要消化的,正是这些挂在
WT_PAGE_MODIFY 上的更新。
参考资料
规范 / 官方文档
- WiredTiger Architecture Guide, Eviction:https://source.wiredtiger.com/develop/arch-eviction.html
- WiredTiger Architecture Guide, Cache
- WiredTiger Architecture Guide, Checkpoint(checkpoint 前借 eviction 减压)
- WiredTiger Architecture Guide, History Store
源码
mongodb-8.0:src/evict/
站内
上一篇:Cache 与
WT_REF
下一篇:B-Tree
与 update chain
同主题继续阅读
把当前热点继续串成多页阅读,而不是停在单篇消费。
【WiredTiger 内核】文档库存储引擎全景:MongoDB 默认引擎的生态位
定位文档库默认引擎 WiredTiger 相对 PG/InnoDB/SQLite/RocksDB 的生态位;钉住 Session→Cache→Reconcile→HS→Checkpoint 主线、站内分工与 17 篇阅读路线,并以 Berenson 隔离词汇与 Durable History 为学术/工程锚点。
【WiredTiger 内核】Cache · Eviction · Reconciliation · History Store · Checkpoint
补齐文档库默认引擎内核层:从 Connection/Session、Cache/Eviction、B-Tree update chain、Reconciliation 到 Timestamps、History Store、Checkpoint/Journal 与 Rollback-to-Stable,并以 MongoDB 嵌入边界与 PG/InnoDB/RocksDB 对照收束。
【WiredTiger 内核】Cache 与 WT_REF:clean/dirty 计量与按需读页
拆解 WiredTiger Cache 的 clean/dirty 计量、WT_REF/WT_PAGE 按需加载,以及 update chain / insert list 如何挂在页上;说明 cache_size 不计 session/cursor,并为 Eviction 章节铺垫 dirty 必须先 reconcile。
【WiredTiger 内核】Reconciliation:内存页到 on-disk image
拆解 WiredTiger reconciliation:把 in-memory 页转为 on-disk image、按 leaf_page_max 与 split_pct 分裂,并在用户表 reconcile 时选出最新已提交值、将更旧更新写入 History Store;锚定 wiki 与 src/reconcile/。