Spark Program | Ckb-probe: Deep Observability Tool for CKB Nodes Based on Aya Kernel eBPF/ckb-probe:基于 Aya 内核 eBPF 的 CKB 节点深度可观测性工具

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:

  1. 五种核心 RocksDB 操作的 uprobe/uretprobe 配对(GET / PUT / WRITE / ITER_NEW / TXN_COMMIT)
  2. 三类 BPF Map — 计数聚合、log2 延迟直方图、超阈值慢操作事件
  3. RocksDbCollector — 用户态采集器,从 Map 读取数据并支持四种展示模式
  4. 输出格式对齐立项书 — 表格 / 直方图 / 慢操作 / JSON 四种模式的视觉规范全部按计划书中落地
  5. EWMA 异常检测(原 Week 5 目标,提前到 Week 4 完成)— 滚动基线 + 5 分钟 warm-up + AVG/P99/绝对 P99 上限三路触发 + Compaction 风暴归因

二、本周交付物

交付项 状态 说明
五对 RocksDB uprobe/uretprobe :white_check_mark: GET / PUT / WRITE / ITER_NEW / TXN_COMMIT 全部挂载成功
OP_STATS 计数聚合 Map :white_check_mark: PerCpuArray,无锁聚合每 op 的 count/total/min/max/bytes
LATENCY_HIST 延迟直方图 Map :white_check_mark: log2 分桶,64 桶覆盖 1ns – 2^63 ns
SLOW_EVENTS 慢操作事件 Map :white_check_mark: PerfEventArray,仅超阈值才输出,常态零开销
RocksDbCollector 用户态采集器 :white_check_mark: 定时轮询、合并 per-CPU 数据、计算 QPS / 百分位 / Bytes/s
ckb-probe rocksdb 子命令 :white_check_mark: 表格 / --histogram / --slow / --json 四种模式
Bytes/s 字节吞吐统计(GET / PUT / TXN_COMMIT 三路) :white_check_mark: GET 走 PinnableSlice 偏移 8 字节读、PUT 走 ctx.arg(5)、TXN_COMMIT 走 per-tid PUT 累加器 snapshot
EWMA 异常检测 + 状态栏 :white_check_mark: 滚动基线、5 min warm-up、AVG×5/P99×3/硬上限三路触发、低 QPS 滑动窗口、抖动期不更新基线
异常归因提示 :white_check_mark: 触发时表格底部输出 ⚠️ ANOMALY DETECTED→ Probable cause: Compaction storm、引导用户运行 --slow
CKB 节点版本自动探测 :white_check_mark: 启动时调用 <binary> --version 写入表头 Node: 字段
BPF verifier 调优 :white_check_mark: log2 全展开、HashMap 限流、saturating_sub 防溢出
真实测试网节点验证 :white_check_mark: 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_NEWrocksdb_writeWriteBatch 内部 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 显式为 null
  • operations{} — 五个 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 查询) :white_check_mark: uretprobe bpf_probe_read_user(ret + 8) 读 PinnableSlice 的 size_
PUT rocksdb_transaction_put_cf 事务内单条写入 :white_check_mark: entry probe 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 事务提交 :white_check_mark: per-tid 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 计划:

  1. 中期报告整理与提交 — Week 2-4 全部交付物的文档汇总:架构图、Map/probe 设计决策、OpStats/SlowEvent/EWMA 三套数据结构说明、可复现验证步骤、--slow/--histogram 真实采样案例分析
  2. CLI 输出润色(基于 clap) — 用 clap 的 derive API 重构参数定义,补齐 #[command(about / long_about / after_help)] 帮助文案、#[arg(value_name / help / default_value)] 元数据与子命令示例;配套 Ctrl+C 退出时清屏复位、窄终端下的降级渲染、错误退出码规范化
  3. Docker 可复现环境搭建(Week 6 任务前移)docker-compose.yml 双容器拓扑(CKB 测试网节点 + ckb-probe sidecar)、env-check.sh 一键自检、三个端到端演示脚本(默认表格 / 直方图 / 慢操作)
  4. 48h 采集报告收集代码逻辑落地 — 新增长跑采集模块(暂定 ckb-probe rocksdb --record <dir> 或独立 collector 二进制),周期性把 OP_STATS / LATENCY_HIST / SLOW_EVENTS / EWMA anomalies[] 落盘成时间序列文件(JSONL 或 Parquet 二选一),同步采样宿主侧 CPU / 内存(/proc/<pid>/stat + status)、事件丢失率(PerfEventArray lost counter)、CKB 同步速度(RPC get_tip_block_number 差分)四项指标,并提供一个简易聚合脚本生成稳定性报告所需的时序数据集
  5. 48h 稳定性测试启动 — Docker 环境 + 采集模块就绪后立即挂起长跑,所有数据通过上述采集逻辑自动落盘,为 Week 6 的报告整理提供可直接喂给绘图脚本的原始数据

Week 6 计划(原计划任务 + Week 5 溢出项):

  1. 48h 稳定性测试收尾与数据整理 — 时序图表、资源消耗汇总、事件保真度报告、延迟分布图表
  2. 两个 RocksDB 诊断场景案例分析 — IBD 写入模式分析 + Compaction 延迟尖峰捕获,作为 Week 7 稳定性报告的核心案例
  3. 针对性优化与健壮性加固 — 根据稳定性测试结果做 CPU / 内存 / 事件丢失三项的针对性优化

里程碑 2 目标已全部达成:ckb-probe rocksdb 在测试网节点上稳定运行,输出有意义的 RocksDB 性能数据,含 EWMA 异常检测与 Compaction 风暴归因。通过 Week 4 的提前收口,Week 5 与 Week 6 合并为完整两周来吃下原定 Week 6 的复杂交付物,避免单周排期失败的风险。

4 Likes