使用 Pebble 替换 oplog 本地落盘队列 - #987
Conversation
|
感谢贡献!~我尽快评估一下 |
|
@SisyphusSQ 非常感谢这个高质量的 PR!整体设计和实现都很扎实,尤其认可几点:用 合并前有几个点想和你确认一下:
期待你的回复,我们一起把它推进到可合并状态~ |
|
逐项确认如下: 1. 配置项语义这里继续沿用现有配置项: full_sync.reader.oplog_store_disk_max_size但会明确说明它在 Pebble spool 下的新语义:
由于 Pebble 的 SST、WAL、MANIFEST 和 compaction 文件模型与 为了避免升级后出现静默语义变化,我会:
启动日志会类似: 2. 持久化与异常退出当前 这里需要同时处理两个边界:
我会重新梳理写入同步和 spool 生命周期策略,避免只依赖正常关闭时的
最终会明确恢复保证:不能产生 oplog 空洞;如果某些异常窗口只能保证至少一次投递,也会把可能重复回放的边界说明并测试清楚。 3. 写入热路径目录扫描这个问题成立。当前每次 这里会改为使用 Pebble 自身维护的: db.Metrics().DiskSpaceUsage()该指标已经包含 WAL、live/obsolete table、MANIFEST 和 compaction 中的本地文件空间,可以避免每次写入遍历目录。 4. Pebble 选型和依赖当前 spool 的业务语义确实是 FIFO,现有调用没有依赖通用随机读能力。Pebble 在这里的主要价值不是随机读,而是:
因此,完整 LSM 提供的随机读能力并不是必需条件。这里的主要取舍,是用相对较重的依赖换取成熟的本地持久化与恢复实现。原方案没有形成与轻量方案之间的量化对比,这部分说明确实不足。 我对比了 Pebble
因此,切换到 v1 可以解决 Go 1.23 的升级问题,并适度缩小依赖树,但不能把 Pebble 变成轻量依赖。 我会优先验证切换到 Pebble 5. 旧注释
diskQueueLastTs = -2 // mark -1 so next time won't call注释确实与代码值不一致,是沿用旧逻辑后没有同步更新,会修改为准确描述 以上调整完成后,我会补充对应测试结果、构建结果和依赖变化,再更新 PR。 |
|
好的,感谢澄清。 |
…rdening PR alibaba#987:强化 Pebble spool 持久化、恢复与清理语义
|
针对前面 review 关注点,本轮主要调整如下:
测试结果(已脱敏):
验收边界:
|
|
@SisyphusSQ 感谢这一轮扎实的修改,我逐项对照了代码,确认关注点都已真正落地:
还有几个纯文档/说明层面的小点,处理完我这边就可以 approve:
整体实现质量很高,感谢你的耐心打磨!补充上述说明后即可合并。 |
|
感谢再次逐项确认,这四点已经补齐:
麻烦再帮忙看一下,感谢! |
背景
关联 issue:#982
当前
full_sync.reader.oplog_store_disk=true路径依赖go-diskqueue作为本地 oplog 临时队列。本 PR 将该路径替换为 Pebble-backed spool,保持原有用户配置入口不变,并补齐 checkpoint、异常重启恢复、指标和测试覆盖。主要变更
collector/spool内部接口和基于 Pebble v1.1.5 的实现,支持 FIFO 批量写入、顺序读取、进程内推进、深度统计、关闭重开、删除和旧格式 fail fast。write_seq和last_write_ts使用同一个 batch,并通过Commit(pebble.Sync)原子同步到可恢复持久点。read_seq仅作为进程内回放游标;spool 重开后从 seq 1 开始 at-least-once replay,并使用 durablelast_write_ts恢复 source reader。Persister的磁盘落盘/回放状态机:全量期间批量写入 Pebble spool,全量完成后顺序回放到 pending queue,worker checkpoint 追平后再进入清理。db.Metrics().DiskSpaceUsage(),不再逐批遍历目录。/persist增加spool_depth、spool_read_seq、spool_write_seq;Prometheus 增加spool_depth、spool_write_seq、spool_read_seq、spool_write_total、spool_read_total、spool_errors_total。full_sync.reader.oplog_store_disk仅用于 oplog fetch method,避免 change stream 路径被误用。兼容性与升级说明
full_sync.reader.oplog_store_disk_max_size,但语义从旧go-diskqueue的单个队列文件字节上限调整为整个 Pebble spool 的 MiB 软上限。默认值256000表示约 250 GiB,并在批次写入前检查;配置注释和启动日志会显示单位、字节换算、作用范围和 spool 路径。go-diskqueue文件或 PR 早期迭代产生的 Pebble schema v1;检测到不兼容格式时 fail fast,并要求先确认 source oplog 覆盖范围再处理遗留目录和 checkpoint。持久化与性能取舍
Commit(pebble.Sync),而不是每条 oplog 执行一次 fsync。NoSync方案,这会增加批次提交延迟,并可能降低峰值写吞吐;本 PR 接受这一取舍,以保证成功返回的批次中 data、write_seq和last_write_ts处于同一个可恢复持久点。不包含
go-diskqueue本地文件或 Pebble schema v1。验证
本地验证
go vet、collector/receiver build 和git diff --check均通过。go test ./collector/spool -count=1、格式检查和git diff --check,结果通过。go test ./...作为通过标准。环境验证
create=false重新打开,6 个 shard 均从 durablelast_write_ts恢复读取,进程、Metrics 与后续 spool 写入正常,错误扫描为 0。验收边界
kill -9验证覆盖 collector 硬崩溃后的 spool 保留、旧 spool 重开和续读恢复;未在该故障轮重复等待整个 full/cleanup/incremental 生命周期。