Skip to content

perf(wal): WAL checkpoint 自清洁——周期重写为热数据快照,令 WAL 有界#157

Merged
NeverENG merged 1 commit into
mainfrom
perf/wal-self-checkpoint
Jul 19, 2026
Merged

perf(wal): WAL checkpoint 自清洁——周期重写为热数据快照,令 WAL 有界#157
NeverENG merged 1 commit into
mainfrom
perf/wal-self-checkpoint

Conversation

@NeverENG

Copy link
Copy Markdown
Owner

背景

standalone 的 WAL 只增不减:数据已刷到 SSTable 后其 WAL 记录仍永久保留,反复覆盖/删除让 WAL 无限膨胀(实测压测后 11MB+),重启重放越来越慢。

改动

每累计 2×MaxMemTableSize 次写触发一次 checkpoint:把 WAL 整体重写为当前未刷盘热数据(active+dirty,含墓碑)快照,回收已落 SSTable 的历史记录,将 WAL 稳态大小约束在热数据量级。

正确性

写路径 wal.Append + storage.Put 两步非原子,二者之间存在"已落 WAL 未进 memtable"窗口。引入 cpMu

  • 每次写持 RLock 罩住两步(写之间仍并发,不影响 group commit);
  • checkpoint 持 Lock 独占,待所有写静默后 active+dirty 快照才必然一致。

快照保留墓碑、区分 nil/空切片,避免被删 key 从 SSTable 复活;重写经 WAL.flushLoop 执行以维持"文件唯一写者"不变式。依赖 SSTable 重载恢复正确#153),否则被回收记录不可恢复。

顺带补上 standalone 缺失的优雅停机 KVServer.Close/Engine.Close(停 memtable 后台协程)。

验证

  • TestCheckpoint_RecoverAcrossSSTableAndTombstone:checkpoint 后跨 SSTable+墓碑恢复。
  • TestCheckpoint_BoundsWALGrowth:小 key 集覆盖写 5000 次断言 WAL 大小有界。
  • 全量 -race 通过。

🤖 Generated with Claude Code

standalone 的 WAL 此前只增不减:即便数据已刷到 SSTable,其 WAL 记录仍永久保留,
反复覆盖写/删除会让 WAL 无限膨胀(实测跑压测后达 11MB+),重启重放也越来越慢。

新增 checkpoint:每累计 2×MaxMemTableSize 次写,把 WAL 整体重写为当前未刷盘热数据
(active+dirty,含墓碑)的快照,回收已落 SSTable 的历史记录,将 WAL 稳态大小约束在
热数据量级。

正确性关键——写路径 append+Put 两步非原子,二者之间存在"已落 WAL 未进 memtable"
的窗口。故引入 cpMu:每次写持 RLock 罩住 append+Put(写之间仍并发,不影响 group
commit),checkpoint 持 Lock 独占,待所有写静默后 active+dirty 快照才必然一致,
此时重写才不丢在途写。快照保留墓碑并区分 nil/空切片,避免被删 key 从 SSTable 复活。
重写经 WAL.flushLoop 执行,维持"文件唯一写者"不变式。依赖 SSTable 重载恢复正确
(见前序 fix(sstable)),否则被回收的记录将不可恢复。

顺带补上 standalone 一直缺的优雅停机 KVServer.Close/Engine.Close(停 memtable 后台
协程),供重启类测试与正常退出使用。

新增测试:checkpoint 后跨 SSTable+墓碑恢复;小 key 集反复覆盖写 5000 次断言 WAL
大小有界(-race 通过)。

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@NeverENG
NeverENG merged commit 51d82b0 into main Jul 19, 2026
3 checks passed
@coderabbitai

coderabbitai Bot commented Jul 19, 2026

Copy link
Copy Markdown

Warning

Review limit reached

@NeverENG, you've reached your PR review limit, so we couldn't start this review.

Next review available in: 30 minutes

Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available.
You're only billed for reviews past your plan's rate limits ($0.25/file).

How can I continue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews.

How do review limits work?

CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability.

For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window.

Please refer docs for additional details.

Review details
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 47151566-6c0f-40a3-8909-d937b5d718b1

📥 Commits

Reviewing files that changed from the base of the PR and between 16ea756 and 9e2d897.

📒 Files selected for processing (6)
  • service/checkpoint_test.go
  • service/fsm.go
  • storage/engine.go
  • storage/istorage/IMemTable.go
  • storage/wal.go
  • storage/zstorage/memtable.go
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch perf/wal-self-checkpoint

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@github-actions

Copy link
Copy Markdown

🐯 BanGD 数据库内核评审

⚠️ 本次未能生成有效的结构化评审(模型返回的内容无法解析)。不阻塞合入,可重试,或改用更强的模型。

模型原始输出片段(调试用)
{}

NeverENG added a commit that referenced this pull request Jul 19, 2026
记录本轮从「PUT 225 qps 反常」出发的完整排障链:实测归因 fsync 瓶颈→
group commit→写恢复测试挖出 SSTable 重载致命 bug(重启丢数据)→WAL 自清洁→
自审堵上原子重写窗口。关联 PR #150/#153/#157/#159/#158。

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant