一张图 + 五条时间线,彻底拆透 StarRocks 主键表 UPSERT 链路

你好,我是 shengjk1,多年大厂经验,努力构建 通俗易懂的、好玩的编程语言教程。 欢迎关注!你会有如下收益:

  1. 了解大厂经验
  2. 拥有和大厂相匹配的技术等

希望看什么,评论或者私信告诉我!

一、 前言

"为什么 StarRocks 主键表可以毫秒级 UPSERT,还能保证点查性能不崩,数据不丢?"

社区里 90% 的调优踩坑,归根结底是没把 dumpapply 这两件事分开。

今天用"一张图 + 五条时间线"把完整读写链路拆到代码级,让你 10 分钟变成"主键表懂王"。


二、 鸟瞰图:把 4 个核心组件先印在脑子里

sql 复制代码
┌────────────┐  1  write  ┌──────────────┐  2  dump   ┌──────────────┐
│ Flink/Java │ ────────►  │ Memory       │ ────────►  │ Disk       │
│ Clients    │  INSERT/   │ DeltaBuffer  │  Mem→Disk  │ Delta RS * │
└────────────┘  UPDATE/   │ (跳表+索引)  │            │ (尚未合并) │
              DELETE      └──────────────┘            └──────────────┘
                                                        │
                                                        │ 3  apply
                                                        ▼
┌────────────┐  4  read   ┌──────────────┐            ┌──────────────┐
│ SQL        │ ◄────────  │ Index        │ ◄────────  │ Base RS      │
│ SELECT     │            │ PrimaryKey   │            │ (已合并)     │
└────────────┘            │ + DelVec     │            └──────────────┘
                          └──────────────┘

一句话注解:
写只碰 DeltaBuffer → dump 只落盘不合并 → apply 才真正把 Delta 合并进 Base → 读永远三路归并。

把这张图截屏当桌面,后面所有概念都能一一映射回来。


2 五条时间线:写 → dump → apply → 读 → 后台维护

2.1 写入:内存里完成 UPSERT,不到 1 ms

步骤 动作 并发保证
① Write Ahead Log 追加写 _wal/xxx.log 崩溃后可重放
② DeltaBuffer 插入 跳表(skiplist)按 pk 排序,同 key 覆盖 行级锁仅怼跳表,无 IO
③ 更新 PK Index 内存 B+ 树直接覆盖 RowLocation 无锁 CAS
④ 返回客户端 纯内存,延迟 P99 < 1 ms ---

关键点:

  • 跳表只保留 最新版本,天然 UPSERT。
  • Base 数据文件零写入,因此没有随机写放大。

2.2 dump:内存 → 磁盘,只写不合并

触发三件套:

  1. 时间间隔:pk_dump_interval_seconds(默认 1 h)。
  2. 内存水位:update_memory_limit_percent 30%。
  3. 文件个数:Delta Rowset ≥ 1000。

内部三步:

  1. 把跳表顺序扫一遍 → 按主键排好序的列存块(含 DELETE 标记)。
  2. 写临时文件 .dat/.idx → 原子 rename 成 DeltaRowsetID
  3. 释放整块 DeltaBuffer,内存瞬间掉回 0。

结果:

  • 查询需要 Union 所有 Delta RS + 残留内存
  • 不会去重 Base,所以 dump 越快,文件越碎,读放大越高。

2.3 apply:磁盘 Delta + Base → 新 Base,真正合并

StarRocks 里叫 update compaction

触发阈值:

  • 总 Delta 大小 ≥ 256 MB(update_compaction_size_threshold)。
  • Delta 文件数 ≥ 1000。
  • 手动 ADMIN COMPACT TABLE tbl;

四步完成:

  1. 选集:挑一个 Base + 若干 Delta(主键区间对齐)。
  2. 多路归并:顺序扫描,同 key 只保留最新一条;遇到 DELETE 就丢弃。
  3. 写新 Base :全新 .dat/.idx/.col/.del 四件套。
  4. 原子切换:元数据版本号 +1,老文件引用计数减 1,GC 线程 5 min 后物理删除。

副作用:

  • CPU 密集 + 读放大(要读旧 Base),但 查询无阻塞(快照隔离)。

2.4 读取:点查 / 范围扫都靠"三路归并"

可见性顺序(从新到旧):

复制代码
内存 DeltaBuffer → 磁盘 Delta RS → Base RS

点查流程:

  1. PK Index 先定位 <RowSetId, RowId>。
  2. 按类型取行:
    • DeltaBuffer → 直接返回。
    • Delta RS → 读主键索引页解析。
    • Base RS → 先查 DelVec,bit=1 表示已删,否则返回。
      范围扫:对三路建迭代器 → 小顶堆归并 → 输出最新版本。

性能关键:

  • PK Index 全内存,点查 O(logN) 毫秒级。
  • Delta RS 越多,堆归并层数越高 → 范围查询 CPU 飙升;因此需要 apply

2.5 后台维护:DelVec / GC / PIndex 重建

  • DelVec
    每份 Base 一份位图,apply 时把删除标记合并进新 Base,旧 DelVec 直接扔。
  • GC
    引用计数为 0 后延迟 5 min 删除,保证正在跑的查询快照不踩空。
  • PK Index 重建
    老版本:BE 重启要扫 全量 Base + Delta 重建 B+ 树,10 亿行≈5 min。
    3.1+:支持 持久化 pindex 快照 ,重启增量恢复,秒级

三、 dump vs apply 对照表:别再混淆!

误区 真相
dump 就是合并 ❌ 只落盘,不去重 Base
dump 越频繁越好 ❌ 文件更碎,读放大,IOPS 爆炸
apply 会锁表 ❌ 快照隔离,读写无锁
DelVec 会无限膨胀 ❌ 每次 apply 生成新 Base,旧位图丢弃
主键表写放大严重 ❌ 写只进内存,零随机写 Base

四、 一张时序图再串一遍(文字版)

ini 复制代码
时间轴 ──►
| 写入 ─┐                    ┌─ dump ─┐               ┌─ apply ─┐
|       │ DeltaBuffer        │ 新 Delta RS            │ 新 Base RS
| key=1 │ v1 → v2 → v3       │ v3 落盘                │ v3 进 Base
| key=2 │ delete             │ delete 标记落盘        │ 丢弃 key=2
| 查询  │ 看 v3              │ 看 v3                   │ 仍看 v3(无锁切换)

五、 总结

StarRocks 主键表 = 内存 DeltaBuffer + 磁盘 Delta/Base + 内存 PKIndex + DelVec 四件套:
写只进内存,dump 不落基线,apply 真正合并,读三路归并,全程无锁。

dump(落盘) vs apply(合并) 这条分界线刻进脑子,

以后任何"UPSERT 延迟高 / 点查毛刺 / 磁盘 IOPS 爆炸"的报警,

你都能 30 秒内说出根因和参数。

相关推荐
回家路上绕了弯2 小时前
订单超时自动取消:从业务场景到技术落地的完整设计方案
分布式·后端
该用户已不存在2 小时前
告别终端低效,10个让同事直呼卧槽的小技巧
后端·命令行
m0_595199852 小时前
Django Rest Framework 和 JWT 身份验证
后端·python·django
m***56722 小时前
【玩转全栈】----Django制作部门管理页面
后端·python·django
嘿嘿2 小时前
使用 Gin 框架加载 HTML 模板:`LoadHTMLGlob` 和 `LoadHTMLFiles` 的比较与优化
后端·go·gin
iOS开发上架哦2 小时前
App Store 上架条件全解析,开发者必备资质、技术要求与跨平台工具指南
后端
月弦笙音3 小时前
【AI】👉提示词入门基础篇指南
前端·后端·aigc
hongweihao4 小时前
Kafka 消息积压了,同事跑路了
后端·spring cloud·kafka
00后程序员4 小时前
App Store 上架 App 的完整指南,从开发准备到 IPA 上传的跨平台实战流程
后端