分支
Kisenon 中的写时复制 Postgres 分支 —— 在 LSN 处分叉、生命周期与级联。
一个分支是指向项目存储中某个日志序列号(LSN)的指针。创建一个 分支是一次 O(1) 的行插入;它不会复制数据。分支随着您向其写入而发散, 并且只存储增量。
模型
每个项目从创建起就有一个 main 分支。从 main(或任何现有分支)
您可以分叉出一个新分支:
- 在 HEAD 处 —— 新分支从父分支的当前 LSN 开始。
- 在特定 LSN 处 —— 新分支从父分支 WAL 保留窗口内的某个历史 LSN 开始。这是"时间旅行"的场景:只要 WAL 仍被保留,您就可以从 过去的某个点分叉。
分支上的读取会回落到父分支的页面,直到分支发散。写入只记录增量。结果:
- 一个带有十个小分支的 100 GB 项目按总共约 100 GB 计费。
- 派生一个分支是亚秒级的。
- 分支是可丢弃的。运行一次破坏性迁移,丢掉该分支,父分支不受影响。
命名
分支名是用户可见的标签,作用域限定到父项目。约束与项目名一致:
- 1–63 个字符。
^[a-zA-Z][a-zA-Z0-9_-]*$。- 在项目内唯一。
内部分支 id(br_<24 hex>)是稳定的引用。在针对 API 编写脚本时,
请使用 id 而非名称;名称可以被重命名。
状态机
一个分支会经历如下状态转换:
creating → ready → deleting → deleted- creating —— 控制平面正在向存储层注册该分支。通常是亚秒级; 如果存储处于负载下则更久。
- ready —— 分支可以挂接到端点并接受写入。
- deleting —— 级联进行中:该分支上的每个端点都在被停止和移除。
- deleted —— 终态。该行会为了可审计性保留一小段时间, 然后被垃圾回收。
CLI 会显示每个分支的当前状态:
keon branches list --project <project-id>创建
keon branches create --project <project-id> --name my-feature --parent main要在某个历史 LSN 处分支,传入 --parent-lsn <lsn>:
keon branches create \
--project <project-id> \
--name pre-migration \
--parent main \
--parent-lsn 0/1A2B3C4D该 LSN 必须在项目的 WAL 保留窗口内。如果它已被压实越过, 分支创建会失败。
删除
删除一个分支会级联到挂接在其上的每个端点:
- 该分支上的所有端点都被停止和移除。
- 分支本身被拆除。
- 存储由 pageserver 压实异步回收。
keon branches delete <branch-id>您无法删除一个项目的 main 分支 —— 请改为删除项目。您可以删除任何
其他分支,即使它有子分支;在那种情况下,子分支会在删除 LSN 处
被重新挂接到被删除分支的父分支上。
重置与恢复
在控制台的分支详情页中,⋯ 操作菜单在任何非根分支上暴露两个 重新分叉操作:
- 重置到父分支 —— 在父分支的当前 HEAD 处重新分叉该分支。 自原始分叉以来在该分支上所做的每一次写入都会被丢弃。该分支上的 端点在切换期间短暂挂起。
- 恢复到时间点 —— 在选定的 LSN 或一个 UTC 时间戳(RFC 3339)处 重新分叉该分支。该点之后的写入会被丢弃。
两者都是异步运行的:控制台发出请求,重新分叉落地后分支返回到
ready。根(main)分支无法被重置 —— 没有可重置到的父分支。
快照
一个快照会固定一个时间点 LSN,使其在 WAL 保留视界之外仍可恢复。 没有快照时,一个恢复目标只在其 WAL 仍被保留期间可达;快照让那个点 无限期地保持可寻址。
分支详情页上的 Snapshots 标签页列出该分支的快照,并允许您捕获 一个新的。每一行提供:
- 恢复 —— 在快照固定的 LSN 处重新分叉该分支。
- 删除 —— 丢弃该快照(底层 LSN 不再被固定,可能被压实回收)。