Week 4 周报:RocksDB 核心探针上线 + ckb-probe rocksdb 子命令
周期:2026-04-06 ~ 2026-04-12
作者:clair
项目:ckb-probe — 基于 eBPF 的 CKB 全节点深度可观测性工具
一、本周目标
进入第二阶段(Phase 2 — RocksDB 核心探针开发)。基于 Week 3 验证通过的 15 个 Tier 1 符号,完成 RocksDB 存储层深度追踪,并提前完成原计划在 Week 5 落地的 EWMA 异常检测模块,从而把里程碑 2 的核心代码工作整体收敛到 Week 4:
- 五种核心 RocksDB 操作的 uprobe/uretprobe 配对(GET / PUT / WRITE / ITER_NEW / TXN_COMMIT)
- 三类 BPF Map — 计数聚合、log2 延迟直方图、超阈值慢操作事件
- RocksDbCollector — 用户态采集器,从 Map 读取数据并支持四种展示模式
- 输出格式对齐立项书 — 表格 / 直方图 / 慢操作 / JSON 四种模式的视觉规范全部按计划书中落地
- EWMA 异常检测(原 Week 5 目标,提前到 Week 4 完成)— 滚动基线 + 5 分钟 warm-up + AVG/P99/绝对 P99 上限三路触发 + Compaction 风暴归因
二、本周交付物
| 交付项 | 状态 | 说明 |
|---|---|---|
| 五对 RocksDB uprobe/uretprobe | GET / PUT / WRITE / ITER_NEW / TXN_COMMIT 全部挂载成功 | |
OP_STATS 计数聚合 Map |
PerCpuArray,无锁聚合每 op 的 count/total/min/max/bytes | |
LATENCY_HIST 延迟直方图 Map |
log2 分桶,64 桶覆盖 1ns – 2^63 ns | |
SLOW_EVENTS 慢操作事件 Map |
PerfEventArray,仅超阈值才输出,常态零开销 | |
RocksDbCollector 用户态采集器 |
定时轮询、合并 per-CPU 数据、计算 QPS / 百分位 / Bytes/s | |
ckb-probe rocksdb 子命令 |
表格 / --histogram / --slow / --json 四种模式 |
|
| Bytes/s 字节吞吐统计(GET / PUT / TXN_COMMIT 三路) | GET 走 PinnableSlice 偏移 8 字节读、PUT 走 ctx.arg(5)、TXN_COMMIT 走 per-tid PUT 累加器 snapshot |
|
| EWMA 异常检测 + 状态栏 | 滚动基线、5 min warm-up、AVG×5/P99×3/硬上限三路触发、低 QPS 滑动窗口、抖动期不更新基线 | |
| 异常归因提示 | 触发时表格底部输出 ⚠️ ANOMALY DETECTED、→ Probable cause: Compaction storm、引导用户运行 --slow |
|
| CKB 节点版本自动探测 | 启动时调用 <binary> --version 写入表头 Node: 字段 |
|
| BPF verifier 调优 | log2 全展开、HashMap 限流、saturating_sub 防溢出 | |
| 真实测试网节点验证 | CKB v0.204.0 测试网节点上四种模式 + 异常检测稳定运行 |
Week 4 核心目标(RocksDB 探针 + 四种展示模式 + Bytes/s 字节吞吐 + EWMA 异常检测)全部达成。原计划留给 Week 5 的 EWMA 模块本周已经一并交付。
三、功能演示
3.1 默认模式 — 实时统计表
$ sudo ckb-probe rocksdb --binary /root/ckb --pid 3310428
✅ attached rocksdb_get_pinned_cf
✅ attached rocksdb_transaction_put_cf
✅ attached rocksdb_write
✅ attached rocksdb_create_iterator_cf
✅ attached rocksdb_transaction_commit
Monitoring 5 operations on PID 3310428 (threshold: 1000μs, interval: 1s)
Press Ctrl+C to stop.
╭─────────────── CKB RocksDB Monitor (PID: 3310428) ───────────────╮
│ Uptime: 00:00:04 Sampling: 2s Node: CKB v0.204.0 │
├────────────┬───────┬─────────┬─────────┬─────────┬───────────────┤
│ Operation │ QPS │ Avg(μs) │ P50(μs) │ P99(μs) │ Bytes/s │
├────────────┼───────┼─────────┼─────────┼─────────┼───────────────┤
│ GET │ 573 │ 1407.2 │ 49.2 │ 12582.9 │ 357.4 KB/s │
│ PUT │ 87 │ 9.0 │ 6.1 │ 49.2 │ 3.2 KB/s │
│ WRITE │ 2 │ 43.9 │ 49.2 │ 49.2 │ — │
│ ITER_NEW │ 30 │ 32.4 │ 24.6 │ 49.2 │ — │
│ TXN_COMMIT │ 27 │ 114.9 │ 98.3 │ 196.6 │ 3.2 KB/s │
╰────────────┴───────┴─────────┴─────────┴─────────┴───────────────╯
Status: ⏳ Warming up — Collecting baseline (296s remaining).
每秒刷新一次。表头自动探测出节点版本 CKB v0.204.0,表格下方的 Status: 行实时展示基线学习/正常/告警三态(详见 §3.5)。5 个 op 中 3 个有真实字节吞吐统计:
- GET ~357 KB/s — uretprobe 中
bpf_probe_read_user直接 peek 返回的PinnableSlice在偏移 8 字节处的size_字段。每次 GET 平均 ~624 B(CKB Block / Header / Cell 真实大小) - PUT ~3.2 KB/s — entry probe 从
ctx.arg(5)读取vlen寄存器值 - TXN_COMMIT ~3.2 KB/s — per-tid
PUT_PENDING_BYTES累加器在 commit 入口 snapshot 后清零;与 PUT 行的 3.2 KB/s 严格相等,正是「每个事务的所有 PUT 在 commit 时被打包结算」的预期行为,是端到端正确性的强信号 - WRITE / ITER_NEW —
rocksdb_write的WriteBatch内部std::string rep_偏移依赖 RocksDB 版本与 libstdc++ 布局,过于脆弱故跳过;ITER_NEW本身无 payload 概念
3.2 --histogram 模式 — log2 分桶延迟分布
$ sudo ckb-probe rocksdb --binary /root/ckb --pid 3310428 --histogram
╭─────────────── CKB RocksDB Monitor (PID: 3310428) ───────────────╮
│ Uptime: 00:00:02 Sampling: 2s Node: CKB v0.204.0 │
├────────────┬───────┬─────────┬─────────┬─────────┬───────────────┤
│ Operation │ QPS │ Avg(μs) │ P50(μs) │ P99(μs) │ Bytes/s │
├────────────┼───────┼─────────┼─────────┼─────────┼───────────────┤
│ GET │ 524 │ 1503.4 │ 49.2 │ 12582.9 │ — │
│ PUT │ 76 │ 9.5 │ 6.1 │ 49.2 │ 2.5 KB/s │
│ WRITE │ 2 │ 55.2 │ 49.2 │ 49.2 │ — │
│ ITER_NEW │ 28 │ 30.0 │ 24.6 │ 98.3 │ — │
│ TXN_COMMIT │ 25 │ 98.8 │ 98.3 │ 196.6 │ — │
╰────────────┴───────┴─────────┴─────────┴─────────┴───────────────╯
GET latency distribution:
2μs │██ 16
4μs │█████████ 54
8μs │███████████████ 92
16μs │████████████████████████████████████████ 239
32μs │███████████████████████████████████████ 235
65μs │█████████████████████████ 155
131μs │█ 9
262μs │ 4
524μs │
1ms │ 4
2ms │███████ 46
4ms │█████████████████████████ 152
8ms │██████ 41
16ms │ 1
PUT latency distribution:
4μs │████████████████████████████████████████ 92
8μs │█████████████████████ 50
16μs │███ 9
32μs │ 2
WRITE latency distribution:
32μs │████████████████████████████████████████ 4
ITER_NEW latency distribution:
16μs │████████████████████████████████████████ 47
32μs │██████ 8
65μs │ 1
TXN_COMMIT latency distribution:
65μs │████████████████████████████████████████ 50
131μs │ 1
GET 的延迟分布是明显的双峰:
- 第一峰位于 ~16-65μs(命中 Block Cache 或 Bloom Filter 快速路径)
- 第二峰位于 ~2-8ms(疑似 Block Cache miss + 磁盘读 / 大 SST 文件查找)
聚合统计的 Avg=1503μs 完全无法揭示这一双峰结构 — 直方图模式正是为捕捉长尾真实形状而存在。后续 Compaction 风暴诊断、Block Cache 容量调优都将依赖这个视图。
3.3 --slow 模式 — 慢操作 box 表格
$ sudo ckb-probe rocksdb --binary /root/ckb --pid 3310428 --slow --threshold 5000
╭───────────────── Slow Operations (threshold: 5000μs) ──────────────────╮
│ Timestamp │ Op │ Latency │ Size │ Note │
├───────────────┼────────────┼───────────┼──────────┼────────────────────┤
│ 34:58.824 │ GET │ 6,046μs │ 1.1 KB │ │
│ 34:58.832 │ GET │ 7,641μs │ 52 B │ │
│ 34:58.839 │ GET │ 7,264μs │ 52 B │ │
│ 34:58.850 │ GET │ 10,692μs │ 52 B │ │
│ 34:58.864 │ GET │ 8,715μs │ 52 B │ │
│ 34:58.872 │ GET │ 7,291μs │ 32 B │ │
│ 34:58.877 │ GET │ 5,476μs │ 240 B │ │
│ 34:58.900 │ GET │ 7,280μs │ 52 B │ │
╰───────────────┴────────────┴───────────┴──────────┴────────────────────╯
Showing 8 of 268 slow operations in last 3s.
--threshold 可调(默认 1000μs),仅延迟超过阈值的事件经 PerfEventArray 推送到用户态,常态零开销。表格保留最近 8 条,底部 Showing N of M in last Ks 展示窗口内累计计数。
Size 列直接揭露慢操作背后的实际数据量 — 上面这一段连续的 GET 慢请求几乎全是 32-52 B 的小读(CKB header hash / cell metadata),延迟却普遍在 5-10 ms 量级,说明慢的不是数据搬运而是 Block Cache miss → 磁盘 SST 查找,而非大对象读取。这是单凭聚合统计无法得到的结论。所有慢请求又集中在同一个 chain-service worker 线程,可作为后续锁竞争 / I/O 瓶颈定位的入口。
3.4 --json 模式 — 机器可读输出
$ sudo ckb-probe rocksdb --binary /root/ckb --pid 3310428 --json
{
"operations": {
"GET": {
"avg_us": 1684.68,
"bytes_per_sec": 309017,
"p50_us": 49.15,
"p99_us": 12582.91,
"qps": 496
},
"PUT": {
"avg_us": 9.53,
"bytes_per_sec": 2542,
"p50_us": 6.14,
"p99_us": 24.58,
"qps": 78
},
"WRITE": {
"avg_us": 44.55,
"bytes_per_sec": null,
"p50_us": 49.15,
"p99_us": 98.3,
"qps": 4
},
"ITER_NEW": {
"avg_us": 29.62,
"bytes_per_sec": null,
"p50_us": 24.58,
"p99_us": 49.15,
"qps": 30
},
"TXN_COMMIT": {
"avg_us": 108.7,
"bytes_per_sec": 2542,
"p50_us": 98.3,
"p99_us": 196.61,
"qps": 26
}
},
"anomalies": [],
"pid": 3310428,
"timestamp": "2026-04-10T13:07:23Z",
"uptime_secs": 2
}
每周期一行 JSON,可直接 | jq 处理或喂给 Prometheus / ELK / Grafana 等下游管线。
关键字段:
timestamp— ISO8601 UTC 时间戳bytes_per_sec— 字节吞吐,未追踪的 op 显式为nulloperations{}— 五个 op 的 QPS / Avg / P50 / P99 / Bytes/s 聚合数据anomalies[]— 当前周期内 EWMA 检测到的延迟尖峰事件,平稳期为空数组,触发时每条含operation/trigger/current_avg_us/baseline_avg_us/multiplier/current_p99_us/baseline_p99_us,下游可直接对接告警管线
3.5 EWMA 异常检测 — 状态栏三态 + Compaction 风暴归因
异常检测始终在线:默认表格每个采样周期都会在底部输出一行 Status:,三种状态:
Status: ⏳ Warming up — Collecting baseline (174s remaining).
启动后 5 分钟内为 warm-up 期,逐 op 收集 EWMA 滚动基线(α=0.05),不报警,避免冷启动假阳性。
Status: ✅ Normal — All latencies within baseline.
平稳期,五个 op 的 avg/P99 都在基线倍数与硬上限以内。
⚠️ ANOMALY DETECTED [13:42:08]
→ GET [P99+CAP] avg 1842.3μs (base 312.4μs, ×5.9) p99 68341.2μs (base 12480.0μs)
→ Probable cause: Compaction storm (WRITE P99 = 4.7ms)
→ Run `ckb-probe rocksdb --slow` for slow operation details.
检测到尖峰时,按触发原因(AVG / P99 / CAP 任意组合)打印每个异常 op,若 WRITE P99 > 1 ms 则附带 Compaction 风暴归因,并提示用户切换到 --slow 模式查看具体慢请求。
触发器同时具备冷启动不误报(5 分钟 warm-up)、瞬时抖动不误报(绝对底 50 μs + 抖动期不更新基线)、持续退化不漏报(绝对 P99 硬上限补盲)、低 QPS op 不被静默(5 秒滑动窗口降级)四项性质。算法参数与实现细节请见技术深度报告 docs/technical-deep-dive.md。
四、五种监控操作
| Op | RocksDB 函数 | CKB 调用路径 | Bytes/s 来源 |
|---|---|---|---|
| GET | rocksdb_get_pinned_cf |
主读路径(Block / Header / Cell 查询) | bpf_probe_read_user(ret + 8) 读 PinnableSlice 的 size_ |
| PUT | rocksdb_transaction_put_cf |
事务内单条写入 | ctx.arg::<usize>(5) 读 vlen 寄存器 |
| WRITE | rocksdb_write |
WriteBatch 原子提交 | — WriteBatch::rep_ 的 std::string 偏移依赖 RocksDB 版本 + libstdc++ ABI,故跳过 |
| ITER_NEW | rocksdb_create_iterator_cf |
区间扫描入口 | — 无 payload 概念 |
| TXN_COMMIT | rocksdb_transaction_commit |
事务提交 | PUT_PENDING_BYTES HashMap 累加器,commit 入口 snapshot 后清零 |
五个操作覆盖 CKB 节点 RocksDB 的全部主要 I/O 类别,3/5 配套真实字节吞吐统计,支撑同步缓慢、Compaction 风暴、Block Cache 退化等运维诊断场景。
五、当前支持的命令
$ ckb-probe --help
Commands:
check Check environment and validate eBPF probes
symbols Analyse a CKB binary for uprobe-attachable symbols
rocksdb Monitor RocksDB operations on a live CKB node via eBPF
| 用法 | 说明 |
|---|---|
ckb-probe rocksdb --binary ./ckb --pid 1234 |
默认实时统计表 |
... --histogram |
表格 + log2 延迟分布柱状图 |
... --slow --threshold 5000 |
慢操作 box 表格(>5ms) |
... --json |
每周期一行 JSON,便于管线集成 |
... --interval 5 |
自定义采样间隔 |
六、下周计划(Week 5–6 合并规划)
为什么本周提前完成里程碑 2: 评估 Week 6 原定任务的工作量后判断单周难以收敛——Docker 双容器拓扑(CKB 测试网节点 + ckb-probe sidecar,含 --privileged / /sys/kernel/debug 挂载、BTF 共享、PID 自动发现)、env-check.sh、三个演示脚本、48h 长跑、性能影响量化(CPU / 内存 / 事件丢失 / 同步速度四项)、两个诊断场景案例分析(IBD 写入模式 + Compaction 延迟尖峰)这套交付物,叠加镜像调试与测试网同步本身的耗时,实际所需工时显著超过一周。因此本周把原计划放在 Week 5 的 EWMA 异常检测一并做完,把里程碑 2 的代码工作整体前移到 Week 4 收口,腾出 Week 5 + Week 6 两整周 用来推进第三阶段。
Week 5 计划:
- 中期报告整理与提交 — Week 2-4 全部交付物的文档汇总:架构图、Map/probe 设计决策、
OpStats/SlowEvent/EWMA 三套数据结构说明、可复现验证步骤、--slow/--histogram真实采样案例分析 - CLI 输出润色(基于 clap) — 用 clap 的
deriveAPI 重构参数定义,补齐#[command(about / long_about / after_help)]帮助文案、#[arg(value_name / help / default_value)]元数据与子命令示例;配套 Ctrl+C 退出时清屏复位、窄终端下的降级渲染、错误退出码规范化 - Docker 可复现环境搭建(Week 6 任务前移) —
docker-compose.yml双容器拓扑(CKB 测试网节点 + ckb-probe sidecar)、env-check.sh一键自检、三个端到端演示脚本(默认表格 / 直方图 / 慢操作) - 48h 采集报告收集代码逻辑落地 — 新增长跑采集模块(暂定
ckb-probe rocksdb --record <dir>或独立collector二进制),周期性把OP_STATS/LATENCY_HIST/SLOW_EVENTS/ EWMAanomalies[]落盘成时间序列文件(JSONL 或 Parquet 二选一),同步采样宿主侧 CPU / 内存(/proc/<pid>/stat+status)、事件丢失率(PerfEventArray lost counter)、CKB 同步速度(RPCget_tip_block_number差分)四项指标,并提供一个简易聚合脚本生成稳定性报告所需的时序数据集 - 48h 稳定性测试启动 — Docker 环境 + 采集模块就绪后立即挂起长跑,所有数据通过上述采集逻辑自动落盘,为 Week 6 的报告整理提供可直接喂给绘图脚本的原始数据
Week 6 计划(原计划任务 + Week 5 溢出项):
- 48h 稳定性测试收尾与数据整理 — 时序图表、资源消耗汇总、事件保真度报告、延迟分布图表
- 两个 RocksDB 诊断场景案例分析 — IBD 写入模式分析 + Compaction 延迟尖峰捕获,作为 Week 7 稳定性报告的核心案例
- 针对性优化与健壮性加固 — 根据稳定性测试结果做 CPU / 内存 / 事件丢失三项的针对性优化
里程碑 2 目标已全部达成:ckb-probe rocksdb 在测试网节点上稳定运行,输出有意义的 RocksDB 性能数据,含 EWMA 异常检测与 Compaction 风暴归因。通过 Week 4 的提前收口,Week 5 与 Week 6 合并为完整两周来吃下原定 Week 6 的复杂交付物,避免单周排期失败的风险。