P4「KV Pool 原型(Rust)」实施计划 —— 系列切片
Context
P3(跨语言联通 + 前缀复用冒烟)已合入 main(235de79)。P3 的 Rust 控制面/池子是 mock:controlplane 用扁平 HashMap<Vec, BlockMeta>(非 radix)、kv-pool 用内存 bytes HashMap、transfer/tiered-store 是空壳,无 ref/配额/GC/分层/RDMA。
P4 要把这些换成生产级 KV Pool 原型。P4 完成判据(docs/00-plan.md:230)= 单测 + micro-benchmark + 用例 (无多节点要求),故跨机/RDMA/真重分布 defer 到 P5,P4 单进程 + 单测模拟。
调研已确认两个复用决策:
B = Dynamo kvbm-logical → fork 抽 crate(in-tree vendor),几乎零耦合,263 测试 + proptest 可跟着走,是 P4 radix/分层/驱逐地基。
A = Mooncake transfer-engine → P4 抄设计(Rust Transport trait + TcpTransport),P5 接入 FFI 加 RdmaTransport。
已定决策(用户拍板)
P4 进程边界 :单进程 + 单测模拟。跨节点(传输/分片重分布)单测模拟,真跨机 defer P5。
A 接入 :P4 抄设计(trait+TcpTransport),P5 接入 Mooncake FFI。P4 不背 CMake+原生库 CI。
B fork 形态 :in-tree vendor(rust/vendor/kvbm-logical + rust/vendor/dynamo-tokens)。
etcd :P4 用 in-memory mock checkpoint(CheckpointStore trait),真 etcd 接入留 P6(控制面 HA)。
架构硬约束(实现必须遵守)
位置视图权威在存储控制面进程内存 (单写者线性一致);etcd/CheckpointStore 只存降频 checkpoint(节点/模型/配额/revision + 位置快照),满块注册不进 etcd。
radix tree 是位置视图权威本身,在控制面进程内存;Router/agent 持只读镜像。
统一编址 L0-L3(层=介质非位置);Location.tier∈{L0,L1,L2} 硬约束(L3 用 l3_present);L2/L3 稳态 XOR;L2=F4 恢复点,L3=SSOT。
ref 两级:一级本地 agent(请求引用+在途传输引用+writeback ref);二级全局汇总(控制面,最终一致,供 tier/GC)。ref 归0 ≠ 删内存,只标可驱逐候选,驱逐覆写才摘视图。
PutEnd 两阶段:agent 本地字节落稳(写 L2 durable)后只调一次 RegisterBlocks=PutEnd;请求结束=写回屏障(flush+ack 所有已注册 block 的 L2 写回,writeback ref 随 durable ack 归零)。满块路 writeback ref 不可驱逐;尾块路(请求结束写一次,不进 radix)。
冷热判定:引用数>0 冻结 + LFU-Aging + 前缀亲和加权保护公共前缀。
迁移主动(promotion/demotion+L0 预放置)+ 被动兜底(读 miss 回填/写满驱逐);后台带宽池<10%,可暂停。
多模型:注册登记 model_id+revision+层数+block_spec+配额;下线级联删 radix 子树;revision 视为新命名空间。
配额软/硬+借用+背压;触硬配额返回写入背压信号(请求级 shedding 仍归 gateway)。
复用决策落地
B = kvbm-logical(fork,in-tree vendor)
架构定位(纠正) :kvbm-logical 是 Dynamo KVBM 三层里的逻辑层 (radix + 状态机 + 驱逐,不含字节 ;字节在 kvbm-physical,运行时在 kvbm-engine)。源码里 BlockMetadata 是空 marker trait,BlockStore slot 存的是 metadata + presence markers,没有 Vec 字节 payload。因此它对应 lake 的 controlplane (位置视图权威);kv-pool 是 dumb 字节后端 ——字节 HashMap 保留,只删掉它自带的「按 hash 索引」职责(归 controlplane)。双进程不矛盾:controlplane 持视图 + 驱逐策略,pool 持字节。
fork 源:3rdparty/dynamo/lib/kvbm-logical/ + 3rdparty/dynamo/lib/tokens/(后者只为 PositionalRadixTree / PositionalLineageHash,3 文件:radix.rs/blocks.rs/lib.rs)。
直接复用:BlockRegistry(registry/mod.rs:109)、PositionalRadixTree(tokens/src/radix.rs:11,两级 DashMap 按 position 分桶)、InactiveIndex trait(pools/store.rs:54)+ backends(LruBackend/MultiLruBackend 4 段频率=LFU-Aging/LineageBackend 前缀亲和)、presence markers(registry/handle.rs:128-188)。不复用 BlockManager /BlockStore (见下驱逐边界)。
P4.1 = 纯 vendor 接入 (GitHub PR #21 ):in-tree rust/vendor/{kvbm-logical,dynamo-tokens},业务源码零改;仅 Cargo 填实版本 / path / edition 2024。不在 P4.1 做源码改造。
fork 源码改造(随 P4.2 / P4.3 按需做,非 P4.1):
InactiveIndex trait + 仅 lake 所需 backends 提 pub:LineageBackend + MultiLruBackend(对照);Authority 主路径 = LineageBackend::with_frequency (叶子≈前缀亲和 + LeafPolicy::Frequency TinyLFU≈LFU-Aging)。Lru/HashMap/Fifo/ReusePolicy 保持 pub(crate) 。lake 不复用 BlockStore slot 池 (见 rust/vendor/UPSTREAM.md)。
拆 EventsManager:删 BlockRegistry.event_manager 字段 + on_block_registered 调用(已有 TODO delegate,registry/mod.rs:91,113),弃用 events/publisher.rs+batcher.rs(NATS 侧)。换 lake in-process 权威 + checkpoint。
LogicalLayoutHandle{G1,G2,G3,G4}(lib.rs:93)→ lake L0-L3;presence HashMap<TypeId,u32> 的 TypeId 换 Tier 枚举。
check_presence 升级锁内读 = 线性一致。
lake 自补(P4.2/P4.3):controlplane 用 BlockRegistry(radix 独立,register_sequence_hash/match_sequence_hash/check_presence)+ InactiveIndex backends(驱逐策略)+ lake 薄驱动(ref→0 标候选、tier 压力取 victim 摘视图),不用 BlockManager/BlockStore ;promote pipeline(抄 kvbm-engine 设计:OffloadPolicy/Pipeline,自写 demotion/promotion);位置视图权威在控制面进程内存 + checkpoint。
A = Mooncake transfer-engine(抄设计,P5 接入)
P4 抄 Transport/TransferTask/BatchDesc/切片+CQ 轮询设计(3rdparty/mooncake/mooncake-transfer-engine/include/transport/transport.h、multi_transport.h),在 rust/transfer 落 Rust trait Transport(submit_transfer/get_status/register_memory/open_segment/allocate_batch_id),P4 只实现 TcpTransport(gRPC 字节走 TcpDataService)。业务面向 trait,P5 加 RdmaTransport(bindgen+薄 FFI 接 A)零业务改动。mooncake-store(L3)依赖中心化 master → 抄设计不接入,L3 用 l3_present 标志 + 薄对象存储回填。
系列切片(依赖链 P4.1→P4.2→P4.3→{P4.4..P4.9};命名用 P4.x,勿与 GitHub PR 号混淆)
P4.1 — B vendor 落地(地基) ✅ / PR #21
P4.2 — 内容寻址 + radix 前缀索引 + 合账骨架 + 驱逐(项 1+2) ✅
架构定位(纠正) :kvbm-logical 是 Dynamo KVBM 三层里的逻辑层 (radix+状态机+驱逐,不含字节;字节在 physical 层)。它对应 lake 的 controlplane (位置视图权威)。kv-pool 是 dumb 字节后端 ——字节 HashMap 保留,只删掉它自带的「按 hash 索引」职责(归 controlplane)。双进程不矛盾:controlplane 持视图+驱逐策略,pool 持字节。
落地澄清(相对本正文,实现切片已对齐) :
命名空间 :P4.2 先按 model_id 一个 BlockRegistry;revision 尚无 proto 字段,正式 (model_id, revision) 留给 P4.5。
RegisterBlocks 与 lineage :RegisterBlocksRequest 增 repeated bytes prefix_hashes(完整有序链);blocks 仍可为 miss 后缀。CP 用全链建 PositionalLineageHash。
EventsManager :本切片断耦不接线(builder 不设);不删 events/ 模块(物理删除留后续小 PR)。
vendor pub 面 / 为何不 pub Lru·Fifo :只公开 controlplane 所需(InactiveIndex + MultiLruBackend + LineageBackend + mark_present/mark_absent;另实现 LeafPolicy::Frequency)。lake 冷热策略=ref>0 冻结 + LFU-Aging + 前缀亲和 → 组合进 LineageBackend::with_frequency (上游 MultiLru 与 Lineage 互斥,lake 走 LeafPolicy 第三臂);MultiLruBackend 仍 pub 对照。纯 LruBackend/Fifo/HashMap 保持 pub(crate)。详见 rust/vendor/UPSTREAM.md。
controlplane:rust/controlplane/src/lib.rs:24 扁平 HashMap<Vec,BlockMeta> → B 的 BlockRegistry+PositionalRadixTree(radix 按 position 分桶;presence markers 记 L0/L1/L2 各几份)。不用 BlockManager (它捆绑 BlockStore,见驱逐边界条)。
kv-pool:rust/kv-pool/src/lib.rs:16 字节 HashMap<(model_id,pool_kind,hash),Vec > 保留 ,删掉 lookup/索引逻辑(命中与否由 controlplane 视图决定),退化为 controlplane 指令下的纯 Put/Get。
hash 迁移 :vendor 用 BlockHash=u64 + PositionalLineageHash(需父链 root(h0).extend(h1)...),lake 现传扁平 Vec 。决策:controlplane 建链 (它拥有 registry 且依赖 vendor):收到有序 prefix_hashes 后,xxh3 Vec →u64,调 PositionalLineageHash::root/extend 重建链,register/match 走 BlockRegistry。proto 的 prefix_hashes 不改,agent 保持 dumb(只转发扁平 hash+字节)。
命名空间 :每 (model_id,revision) 一个 BlockRegistry 实例(对齐 P4.5「按命名空间剪枝」);PositionalRadixTree 按 position 分桶,不含 model_id,靠实例隔离。
T = lake BlockMeta :BlockMetadata 是 blanket impl(blocks/mod.rs:56),lake BlockMeta(locations+ref_count+l3_present)直接当 T,挂在 ImmutableBlock 的 HandleInner;vendor presence markers(HashMap<TypeId,u32>)的 TypeId 换 Tier(P4.1 改造点3),lake BlockMeta.locations 保留作位置细节权威(tier+node+segment+offset),presence 计数供驱逐/tier 逻辑。
ReportRef = 合账骨架 (P4.2):累加 global_refs,忽略 RefKind ;agent 本地一级 / 分 kind → 后续。驱逐主路径=LineageBackend::with_frequency(叶子≈前缀亲和 + TinyLFU≈LFU-Aging);MultiLruBackend 对照。ref 归0 标候选不删,覆写才摘视图。 inactive 上界对齐 Dynamo:report_ref 满容只 skip insert;压力 allocate 只走显式路径(evict_n / 后续生产 allocate)。
驱逐复用边界 :BlockRegistry 负责 radix+presence;InactiveIndex 负责选 victim。薄驱动对齐 Dynamo 路径拆分:ref→0 → inactive.insert(满容 skip,不摘视图);压力 allocate 另路径(显式 evict_n / 后续生产,对应 allocate_atomic)。不用 BlockStore 。
新增 proto:ReportRef(stream RefDelta)+RefDelta(RefKind wire 预留;P4.2 CP 忽略;流式全有或全无)。
验证 (命中 P4 判据两条):前缀复用命中率单测;驱逐正确性=Authority 单测 (含 Lineage+Frequency、inactive 上界 skip insert、批内不压力驱逐);生产 ReportRef 喂数 / 压力 allocate → 后续切片。
P4.3 — 分层缓存引擎 L0-L3 + PutEnd 两阶段 + writeback ref(项 3) ✅(判据满足) / PR #31 (待合)
rust/tiered-store:LocalTierEngine L0–L3 内存站位 + presence 经 CP publish_location/l3_present;promotion/demotion/读 miss/写满驱逐;L2/L3 稳态 XOR(写回只 L2;L3=demote/cap)。真 NVMe/对象存储 defer P5。
PutEnd:commit_through 时序 flush → pin → register → WRITEBACK+1 → barrier → WRITEBACK−1 (durable-first COMPLETE;barrier 后才解冻,对齐 SGLang lock_ref)。
storage-agent:ControlPlanePort/AuthorityPort 进程内接线(真 tonic 客户端后续)。
TierPipeline + BandwidthPool(先占预算再 mutate);完整调参留 P7。
验证 :命中率/成本曲线单测;PutEnd/writeback 阻驱逐;benches/tier_access criterion 已跑通。
合入后遗留(不挡 P4.3,记入下方 P4.7 / P5 / P6 / P7) :见本 issue 评论「PR feat(P4): P4.3 完成——L0–L3 站位 / PutEnd / pipeline / 命中率验证 #31 review 遗留」——barrier 失败 inactive 窗口、WRITEBACK−1 失败永久冻结、apply_location_events 非原子、L1 无私有 CP 事件、segment 占位、lookup 懒修复写锁、hop 成本校准等。
P4.4 — TCP 数据面 + Transport 抽象(项 4,TCP-first)
rust/transfer 落 Transport trait + TcpTransport(gRPC 字节走 TcpDataService)。SkeletonKvService 正名为 TcpDataService (保留 PutBlocks/GetBlocks 作 TCP 字节路径,对齐 Mooncake MC_FORCE_TCP fallback)。TransferService(SubmitTransfer/GetTransferStatus/Pull/Publish)接线 TcpTransport:单进程下"传输"=本地拷贝/gRPC 字节搬运。
Location.tier∈{L0,L1,L2} 硬约束校验(拒绝 tier=L3)。
P4.3 遗留(随真介质) :register_request 的 segment_id:1, offset:0 占位 → P5 真 NVMe placement 填实(P4.4 若先接 TCP 段映射也可顺手,但权威在 P5)。
复用 :A 抄设计,不接入 Mooncake。
验证 :SubmitTransfer→GetTransferStatus 端到端单测;tier=L3 拒绝单测;Pull/Publish layer-wise 增量单测。
P4.5 — 多模型生命周期(项 6)
模型注册/下线/revision。注册登记 model_id+revision+num_layers+block_spec+hash_algo+配额;下线级联删 radix 子树;revision 视为新命名空间。
新增 proto:RegisterModel/DeregisterModel+ModelDescriptor(挂 ControlPlaneService)。
复用 :B PositionalRadixTree 按命名空间剪枝。
验证 (命中"多模型隔离"条):两模型同前缀 hash 不串扰;下线级联删(radix 子树清空+locations 摘视图);revision 失效。
P4.6 — 按模型配额 + 借用 + 背压(项 7)
每 (model_id,revision) 软/硬配额+借用;触硬配额→池返回写入背压信号(请求级 shedding 仍归 gateway,lake 只上报)。配额计数挂 P4.5 命名空间。
新增 proto:SetModelQuota/GetModelQuota+Quota/BackpressureSignal。
验证 (命中"配额"条):A 触硬配额不影响 B;借用回收;背压信号触发。
P4.7 — GC:冷块/孤儿块回收 + 崩溃 reconcile(项 8)
冷块回收(ref 归0+LFU-Aging 冷度达标→摘视图+删 L0/L1 副本,L2/L3 留 durable 后盾);孤儿块回收(写入屏障标记未完成,TTL 后回收,对齐 Mooncake zombie put_start_discard_timeout);崩溃 reconcile(从 CheckpointStore 重建位置视图+agent 上报对账,元数据先于字节删除)。
writeback ref 泄漏兜底(P4.3 遗留) :PutEndSession::commit_through 在 WRITEBACK+1 上报 CP 后、barrier(WRITEBACK-1)前若 agent 崩溃,CP 侧 global_refs 永不归零→该 prefix radix 永久冻结驱逐(泄漏)。Mooncake 走会话级 put_start_discard_timeout;lake 不做会话级 TTL,改由节点级崩溃 reconcile 兜底——agent 心跳过期→扫该 agent 全部 ref 批量清 + 摘该节点 L0 location(节点下线 reconcile 本就覆盖此,writeback ref 泄漏是其子集)。即 P4.7 实现节点级 reconcile 即顺带解决,无需独立会话超时机制。
PutEnd barrier 失败 → inactive 窗口(P4.3 review feat(P4): P4.3 完成——L0–L3 站位 / PutEnd / pipeline / 命中率验证 #31 §4.1) :register 成功后 RequestBarrier 失败会 WRITEBACK−1 回滚 +1,global_refs 可能归 0 → 立刻 inactive.insert。语义上「无人持有」正确,但真 tonic 重试 + 并发驱逐窗口需在 reconcile / sticky 持有策略中收紧(见 putend.rs 注释)。
barrier 成功但 WRITEBACK−1 失败(P4.3 review) :CP 侧可能永久冻结;节点级 reconcile 扫泄漏 ref 一并兜底。
apply_location_events 非原子(P4.3 review) :批量事件中途失败可留半更新视图;P4.7/后续补事务或补偿。
CheckpointStore trait + in-memory mock 实现(P4);真 etcd 留 P6。
新增 proto:ReconcileOrphans/DiscardBlocks+OrphanReport+Checkpoint/CheckpointSnapshot。
验证 (命中"GC"条):冷块回收正确+durable 后盾保留;孤儿块 TTL 回收;崩溃 reconcile(checkpoint 重建+元数据先于字节删);含上列 P4.3 遗留窗口单测或注入场景。
P4.8 — 碎片整理:逻辑共置 + 物理压实(项 9)
逻辑共置(同前缀 block 物理邻近)+ 物理压实(回收段内空洞);后台带宽池<10%,节流可暂停。依赖 P4.7 摘块。
新增 proto(可选):TriggerDefrag/PauseBackground。
验证 (命中"碎片整理"条):压实前后段利用率;共置后前缀连续性;节流暂停可恢复。
P4.9 — 一致性哈希分片(项 5,单测;真重分布 defer P5)
一致性哈希环 + shard map + 节点增删 block 所有权迁移逻辑 (扩容仅迁移落新节点区间;缩容 Drain 推 L2 再下线)。P4 只单测模拟(虚拟节点环/增删区间重算/Drain 标记),不做真实跨节点字节迁移。
新增 proto(可选):GetShardMap。
验证 :环 membership 单测;扩容最小迁移;缩容 Drain 推 L2。真跨机 defer P5。
proto 增量汇总
新增 RPC(挂 ControlPlaneService,保持单服务):
RPC
用途
切片
ReportRef(stream RefDelta) -> Ack
合账骨架(忽略 RefKind;agent 未上报)
P4.2
RegisterModel/DeregisterModel
模型注册/下线级联删
P4.5
SetModelQuota/GetModelQuota
软/硬配额+借用+背压
P4.6
ReconcileOrphans/DiscardBlocks
GC reconcile + 显式摘块
P4.7
TriggerDefrag/PauseBackground(可选)
碎片整理+后台暂停
P4.8
GetShardMap(可选)
查 shard 分布(调试)
P4.9
新增消息:RefDelta(ref_kind 枚举)、ModelDescriptor、Quota/BackpressureSignal、OrphanReport、Checkpoint/CheckpointSnapshot、ShardMap/ShardEntry、各 RPC Request/Response。
SkeletonKvService → 正名 TcpDataService(保留,作 TCP 退化数据面;proto 注释 lake.proto 已留此口)。schema.proto 无需改结构(L0-L3/Tier/Location/BlockMeta 已定稿);BlockSpec 挂 ModelDescriptor,不进 KVBlockID 寻址。
实施起点
先做 P4.1 (纯 vendor;已由 PR #21 落地),再逐个推进 P4.2–P4.9。每个切片独立分支独立 review(走 GitHub PR 流程,不直推 main)。
验证(整体)
每个 PR 的验证见上。P4 整体完成判据(docs/00-plan.md:230):
前缀复用命中率 + 驱逐正确性单测 → P4.2
吞吐 micro-benchmark → P4.3
多模型隔离/配额/GC/碎片整理各有验证用例 → P4.5/P4.6/P4.7/P4.8
CI:build.yml(rust fmt/clippy/build/stub-drift)持续绿;P4 新增的 vendor crate 加入 build/clippy/test 门。
关键文件
proto/lake.proto、proto/schema.proto(proto 增量,各 PR)
rust/Cargo.toml(加 vendor 成员,P4.1)
rust/vendor/kvbm-logical/、rust/vendor/dynamo-tokens/(P4.1 fork)
rust/controlplane/src/lib.rs(radix 权威/ref/模型/配额/GC/分片,P4.2/P4.5/P4.6/P4.7/P4.9)
rust/kv-pool/src/lib.rs(dumb 字节后端,删索引职责,P4.2)
rust/tiered-store/src/lib.rs(分层引擎+PutEnd+压实,P4.3/P4.8)
rust/transfer/src/lib.rs(Transport trait+TcpTransport,P4.4)
rust/storage-agent/src/lib.rs(本地记账/TransferService/Drain,P4.3/P4.4/P4.7/P4.9)
fork 参考:3rdparty/dynamo/lib/kvbm-logical/src/{registry/mod.rs,pools/store.rs,manager/mod.rs}、3rdparty/dynamo/lib/tokens/src/radix.rs、3rdparty/mooncake/mooncake-transfer-engine/include/transport/transport.h
遵守 CLAUDE.md reference 规则
每个切片实现前,对照 docs/research/3rdparty-reference.md + 对应分目录文档,显式说明参考了哪个实现(file:符号)、借鉴什么、lake 关键差异。P4.1/P4.2 参考 Dynamo kvbm-logical;P4.4 参考 Mooncake transfer-engine;P4.3 promote pipeline 参考 kvbm-engine OffloadPolicy/Pipeline。
本 issue 由 P4 规划生成,作为 P4 系列切片(P4.1–P4.9)的总跟踪。每个切片对应的 GitHub PR 合入后在此勾选进度。
P4「KV Pool 原型(Rust)」实施计划 —— 系列切片
Context
P3(跨语言联通 + 前缀复用冒烟)已合入 main(
235de79)。P3 的 Rust 控制面/池子是 mock:controlplane用扁平HashMap<Vec, BlockMeta>(非 radix)、kv-pool用内存 bytes HashMap、transfer/tiered-store是空壳,无 ref/配额/GC/分层/RDMA。P4 要把这些换成生产级 KV Pool 原型。P4 完成判据(
docs/00-plan.md:230)= 单测 + micro-benchmark + 用例(无多节点要求),故跨机/RDMA/真重分布 defer 到 P5,P4 单进程 + 单测模拟。调研已确认两个复用决策:
Transporttrait +TcpTransport),P5 接入 FFI 加RdmaTransport。已定决策(用户拍板)
rust/vendor/kvbm-logical+rust/vendor/dynamo-tokens)。CheckpointStoretrait),真 etcd 接入留 P6(控制面 HA)。架构硬约束(实现必须遵守)
l3_present);L2/L3 稳态 XOR;L2=F4 恢复点,L3=SSOT。RegisterBlocks=PutEnd;请求结束=写回屏障(flush+ack 所有已注册 block 的 L2 写回,writeback ref 随 durable ack 归零)。满块路 writeback ref 不可驱逐;尾块路(请求结束写一次,不进 radix)。复用决策落地
B = kvbm-logical(fork,in-tree vendor)
架构定位(纠正):kvbm-logical 是 Dynamo KVBM 三层里的逻辑层(radix + 状态机 + 驱逐,不含字节;字节在 kvbm-physical,运行时在 kvbm-engine)。源码里
BlockMetadata是空 marker trait,BlockStoreslot 存的是 metadata + presence markers,没有Vec字节 payload。因此它对应 lake 的 controlplane(位置视图权威);kv-pool 是 dumb 字节后端——字节 HashMap 保留,只删掉它自带的「按 hash 索引」职责(归 controlplane)。双进程不矛盾:controlplane 持视图 + 驱逐策略,pool 持字节。fork 源:
3rdparty/dynamo/lib/kvbm-logical/+3rdparty/dynamo/lib/tokens/(后者只为PositionalRadixTree/PositionalLineageHash,3 文件:radix.rs/blocks.rs/lib.rs)。直接复用:
BlockRegistry(registry/mod.rs:109)、PositionalRadixTree(tokens/src/radix.rs:11,两级 DashMap 按 position 分桶)、InactiveIndextrait(pools/store.rs:54)+ backends(LruBackend/MultiLruBackend4 段频率=LFU-Aging/LineageBackend前缀亲和)、presence markers(registry/handle.rs:128-188)。不复用BlockManager/BlockStore(见下驱逐边界)。P4.1 = 纯 vendor 接入(GitHub PR #21):in-tree
rust/vendor/{kvbm-logical,dynamo-tokens},业务源码零改;仅 Cargo 填实版本 / path / edition 2024。不在 P4.1 做源码改造。fork 源码改造(随 P4.2 / P4.3 按需做,非 P4.1):
InactiveIndextrait + 仅 lake 所需 backends 提pub:LineageBackend+MultiLruBackend(对照);Authority 主路径 =LineageBackend::with_frequency(叶子≈前缀亲和 +LeafPolicy::FrequencyTinyLFU≈LFU-Aging)。Lru/HashMap/Fifo/ReusePolicy保持pub(crate)。lake 不复用BlockStoreslot 池(见rust/vendor/UPSTREAM.md)。EventsManager:删BlockRegistry.event_manager字段 +on_block_registered调用(已有 TODO delegate,registry/mod.rs:91,113),弃用events/publisher.rs+batcher.rs(NATS 侧)。换 lake in-process 权威 + checkpoint。LogicalLayoutHandle{G1,G2,G3,G4}(lib.rs:93)→ lakeL0-L3;presenceHashMap<TypeId,u32>的 TypeId 换 Tier 枚举。check_presence升级锁内读 = 线性一致。lake 自补(P4.2/P4.3):controlplane 用
BlockRegistry(radix 独立,register_sequence_hash/match_sequence_hash/check_presence)+InactiveIndexbackends(驱逐策略)+ lake 薄驱动(ref→0 标候选、tier 压力取 victim 摘视图),不用BlockManager/BlockStore;promote pipeline(抄 kvbm-engine 设计:OffloadPolicy/Pipeline,自写 demotion/promotion);位置视图权威在控制面进程内存 + checkpoint。A = Mooncake transfer-engine(抄设计,P5 接入)
P4 抄
Transport/TransferTask/BatchDesc/切片+CQ 轮询设计(3rdparty/mooncake/mooncake-transfer-engine/include/transport/transport.h、multi_transport.h),在rust/transfer落 Rust traitTransport(submit_transfer/get_status/register_memory/open_segment/allocate_batch_id),P4 只实现TcpTransport(gRPC 字节走TcpDataService)。业务面向 trait,P5 加RdmaTransport(bindgen+薄 FFI 接 A)零业务改动。mooncake-store(L3)依赖中心化 master → 抄设计不接入,L3 用l3_present标志 + 薄对象存储回填。系列切片(依赖链 P4.1→P4.2→P4.3→{P4.4..P4.9};命名用 P4.x,勿与 GitHub PR 号混淆)
P4.1 — B vendor 落地(地基) ✅ / PR #21
kvbm-logical+dynamo-tokens入rust/vendor/(纯构建接入,业务源码未改)。rust/Cargo.toml加两个 vendor 成员;UPSTREAM.mdpin + LICENSE;CIcargo test -p dynamo-tokens -p kvbm-logical。P4.2 — 内容寻址 + radix 前缀索引 + 合账骨架 + 驱逐(项 1+2) ✅
架构定位(纠正):kvbm-logical 是 Dynamo KVBM 三层里的逻辑层(radix+状态机+驱逐,不含字节;字节在 physical 层)。它对应 lake 的 controlplane(位置视图权威)。kv-pool 是 dumb 字节后端——字节 HashMap 保留,只删掉它自带的「按 hash 索引」职责(归 controlplane)。双进程不矛盾:controlplane 持视图+驱逐策略,pool 持字节。
落地澄清(相对本正文,实现切片已对齐):
命名空间:P4.2 先按
model_id一个BlockRegistry;revision尚无 proto 字段,正式(model_id, revision)留给 P4.5。RegisterBlocks 与 lineage:
RegisterBlocksRequest增repeated bytes prefix_hashes(完整有序链);blocks仍可为 miss 后缀。CP 用全链建PositionalLineageHash。EventsManager:本切片断耦不接线(builder 不设);不删
events/模块(物理删除留后续小 PR)。vendor pub 面 / 为何不 pub Lru·Fifo:只公开 controlplane 所需(
InactiveIndex+MultiLruBackend+LineageBackend+mark_present/mark_absent;另实现LeafPolicy::Frequency)。lake 冷热策略=ref>0冻结 + LFU-Aging + 前缀亲和 → 组合进LineageBackend::with_frequency(上游 MultiLru 与 Lineage 互斥,lake 走 LeafPolicy 第三臂);MultiLruBackend仍 pub 对照。纯LruBackend/Fifo/HashMap保持pub(crate)。详见rust/vendor/UPSTREAM.md。rust/controlplane/src/lib.rs:24扁平HashMap<Vec,BlockMeta>→ B 的BlockRegistry+PositionalRadixTree(radix 按 position 分桶;presence markers 记 L0/L1/L2 各几份)。不用BlockManager(它捆绑BlockStore,见驱逐边界条)。rust/kv-pool/src/lib.rs:16字节HashMap<(model_id,pool_kind,hash),Vec >保留,删掉 lookup/索引逻辑(命中与否由 controlplane 视图决定),退化为 controlplane 指令下的纯 Put/Get。BlockHash=u64+PositionalLineageHash(需父链root(h0).extend(h1)...),lake 现传扁平Vec。决策:controlplane 建链(它拥有 registry 且依赖 vendor):收到有序prefix_hashes后,xxh3Vec→u64,调PositionalLineageHash::root/extend重建链,register/match 走BlockRegistry。proto 的prefix_hashes不改,agent 保持 dumb(只转发扁平 hash+字节)。(model_id,revision)一个BlockRegistry实例(对齐 P4.5「按命名空间剪枝」);PositionalRadixTree按 position 分桶,不含 model_id,靠实例隔离。BlockMetadata是 blanket impl(blocks/mod.rs:56),lakeBlockMeta(locations+ref_count+l3_present)直接当 T,挂在ImmutableBlock的HandleInner;vendor presence markers(HashMap<TypeId,u32>)的 TypeId 换 Tier(P4.1 改造点3),lakeBlockMeta.locations保留作位置细节权威(tier+node+segment+offset),presence 计数供驱逐/tier 逻辑。global_refs,忽略RefKind;agent 本地一级 / 分 kind → 后续。驱逐主路径=LineageBackend::with_frequency(叶子≈前缀亲和 + TinyLFU≈LFU-Aging);MultiLruBackend对照。ref 归0 标候选不删,覆写才摘视图。 inactive 上界对齐 Dynamo:report_ref满容只 skip insert;压力allocate只走显式路径(evict_n/ 后续生产 allocate)。BlockRegistry负责 radix+presence;InactiveIndex负责选 victim。薄驱动对齐 Dynamo 路径拆分:ref→0 →inactive.insert(满容 skip,不摘视图);压力allocate另路径(显式evict_n/ 后续生产,对应allocate_atomic)。不用BlockStore。ReportRef(stream RefDelta)+RefDelta(RefKindwire 预留;P4.2 CP 忽略;流式全有或全无)。ReportRef喂数 / 压力 allocate → 后续切片。P4.3 — 分层缓存引擎 L0-L3 + PutEnd 两阶段 + writeback ref(项 3) ✅(判据满足) / PR #31(待合)
rust/tiered-store:LocalTierEngineL0–L3 内存站位 + presence 经 CPpublish_location/l3_present;promotion/demotion/读 miss/写满驱逐;L2/L3 稳态 XOR(写回只 L2;L3=demote/cap)。真 NVMe/对象存储 defer P5。commit_through时序 flush → pin → register → WRITEBACK+1 → barrier → WRITEBACK−1(durable-first COMPLETE;barrier 后才解冻,对齐 SGLanglock_ref)。storage-agent:ControlPlanePort/AuthorityPort进程内接线(真 tonic 客户端后续)。TierPipeline+BandwidthPool(先占预算再 mutate);完整调参留 P7。benches/tier_accesscriterion 已跑通。apply_location_events非原子、L1 无私有 CP 事件、segment 占位、lookup 懒修复写锁、hop 成本校准等。P4.4 — TCP 数据面 + Transport 抽象(项 4,TCP-first)
rust/transfer落Transporttrait +TcpTransport(gRPC 字节走TcpDataService)。SkeletonKvService正名为TcpDataService(保留 PutBlocks/GetBlocks 作 TCP 字节路径,对齐 MooncakeMC_FORCE_TCPfallback)。TransferService(SubmitTransfer/GetTransferStatus/Pull/Publish)接线TcpTransport:单进程下"传输"=本地拷贝/gRPC 字节搬运。Location.tier∈{L0,L1,L2}硬约束校验(拒绝 tier=L3)。register_request的segment_id:1, offset:0占位 → P5 真 NVMe placement 填实(P4.4 若先接 TCP 段映射也可顺手,但权威在 P5)。P4.5 — 多模型生命周期(项 6)
RegisterModel/DeregisterModel+ModelDescriptor(挂 ControlPlaneService)。PositionalRadixTree按命名空间剪枝。P4.6 — 按模型配额 + 借用 + 背压(项 7)
(model_id,revision)软/硬配额+借用;触硬配额→池返回写入背压信号(请求级 shedding 仍归 gateway,lake 只上报)。配额计数挂 P4.5 命名空间。SetModelQuota/GetModelQuota+Quota/BackpressureSignal。P4.7 — GC:冷块/孤儿块回收 + 崩溃 reconcile(项 8)
put_start_discard_timeout);崩溃 reconcile(从CheckpointStore重建位置视图+agent 上报对账,元数据先于字节删除)。PutEndSession::commit_through在 WRITEBACK+1 上报 CP 后、barrier(WRITEBACK-1)前若 agent 崩溃,CP 侧global_refs永不归零→该 prefix radix 永久冻结驱逐(泄漏)。Mooncake 走会话级put_start_discard_timeout;lake 不做会话级 TTL,改由节点级崩溃 reconcile兜底——agent 心跳过期→扫该 agent 全部 ref 批量清 + 摘该节点 L0 location(节点下线 reconcile 本就覆盖此,writeback ref 泄漏是其子集)。即 P4.7 实现节点级 reconcile 即顺带解决,无需独立会话超时机制。register成功后RequestBarrier失败会WRITEBACK−1回滚 +1,global_refs可能归 0 → 立刻inactive.insert。语义上「无人持有」正确,但真 tonic 重试 + 并发驱逐窗口需在 reconcile / sticky 持有策略中收紧(见putend.rs注释)。apply_location_events非原子(P4.3 review):批量事件中途失败可留半更新视图;P4.7/后续补事务或补偿。CheckpointStoretrait + in-memory mock 实现(P4);真 etcd 留 P6。ReconcileOrphans/DiscardBlocks+OrphanReport+Checkpoint/CheckpointSnapshot。P4.8 — 碎片整理:逻辑共置 + 物理压实(项 9)
TriggerDefrag/PauseBackground。P4.9 — 一致性哈希分片(项 5,单测;真重分布 defer P5)
GetShardMap。proto 增量汇总
新增 RPC(挂
ControlPlaneService,保持单服务):ReportRef(stream RefDelta) -> AckRegisterModel/DeregisterModelSetModelQuota/GetModelQuotaReconcileOrphans/DiscardBlocksTriggerDefrag/PauseBackground(可选)GetShardMap(可选)新增消息:
RefDelta(ref_kind 枚举)、ModelDescriptor、Quota/BackpressureSignal、OrphanReport、Checkpoint/CheckpointSnapshot、ShardMap/ShardEntry、各 RPC Request/Response。SkeletonKvService→ 正名TcpDataService(保留,作 TCP 退化数据面;proto 注释lake.proto已留此口)。schema.proto无需改结构(L0-L3/Tier/Location/BlockMeta 已定稿);BlockSpec挂ModelDescriptor,不进KVBlockID寻址。实施起点
先做 P4.1(纯 vendor;已由 PR #21 落地),再逐个推进 P4.2–P4.9。每个切片独立分支独立 review(走 GitHub PR 流程,不直推 main)。
验证(整体)
每个 PR 的验证见上。P4 整体完成判据(
docs/00-plan.md:230):CI:
build.yml(rust fmt/clippy/build/stub-drift)持续绿;P4 新增的 vendor crate 加入 build/clippy/test 门。关键文件
proto/lake.proto、proto/schema.proto(proto 增量,各 PR)rust/Cargo.toml(加 vendor 成员,P4.1)rust/vendor/kvbm-logical/、rust/vendor/dynamo-tokens/(P4.1 fork)rust/controlplane/src/lib.rs(radix 权威/ref/模型/配额/GC/分片,P4.2/P4.5/P4.6/P4.7/P4.9)rust/kv-pool/src/lib.rs(dumb 字节后端,删索引职责,P4.2)rust/tiered-store/src/lib.rs(分层引擎+PutEnd+压实,P4.3/P4.8)rust/transfer/src/lib.rs(Transport trait+TcpTransport,P4.4)rust/storage-agent/src/lib.rs(本地记账/TransferService/Drain,P4.3/P4.4/P4.7/P4.9)3rdparty/dynamo/lib/kvbm-logical/src/{registry/mod.rs,pools/store.rs,manager/mod.rs}、3rdparty/dynamo/lib/tokens/src/radix.rs、3rdparty/mooncake/mooncake-transfer-engine/include/transport/transport.h遵守 CLAUDE.md reference 规则
每个切片实现前,对照
docs/research/3rdparty-reference.md+ 对应分目录文档,显式说明参考了哪个实现(file:符号)、借鉴什么、lake 关键差异。P4.1/P4.2 参考 Dynamo kvbm-logical;P4.4 参考 Mooncake transfer-engine;P4.3 promote pipeline 参考 kvbm-engineOffloadPolicy/Pipeline。