04 分布式存储:把可复用状态放进共享资源池
推理缓存可以先当作一组不可变对象理解。存储系统负责对象身份、位置、空间、发布、读保护和回收;是否对应某个模型前缀,还要由上层缓存协议保证。
重点教材与设计文档
- KV Cache 存储详解:从数据模型、读写协议到容量/网络预算、策略和故障验收。
- LMCache + Mooncake 联合实现:把引擎、L1、native adapter、Store 与 TE 的两条数据链讲完整。
- 设计图册:部署与故障域、对象协议、联合架构和运行图。
- 专家面试总纲:P7–P8 能力参考、十组深挖问题与系统设计。
1. 先区分目录和数据
控制路径:key → 查询位置/状态 → 分配或选取副本 → 获取保护与完成信息
数据路径:源 buffer → 目标存储空间 → 读取者 buffer
持有目录的服务不一定转发全部 payload。目录故障与存放数据的节点故障也不是同一件事,恢复策略必须分别考虑。
2. 用一写一读理解共同协议
写入通常需要“保留空间 → 写字节 → 确认完整 → 发布可读”。这是一种设计模型,不规定每个实现必须暴露四个同名接口。核心不变量是:读者不能把未完成对象当作完整缓存。
读取通常需要“查位置 → 检查副本 → 保护读取期间的资源 → 读数据 → 检查完成 → 解除保护”。TTL、租约和引用计数作用不同:到期时间不自动保证在途访问安全,保护协议也不保证对象永远存在。
3. 主要设计取舍
| 问题 | 要作出的选择 | 常见误区 |
|---|---|---|
| 空间从哪来 | 独立存储进程或客户端贡献的内存/磁盘 | 把进程退出后消失的内存当作持久介质 |
| 数据放哪 | 分配器、placement、负载和故障域 | 把两个 segment 当作两台独立物理机 |
| 保留多少副本 | 容量、读取压力、可用性和复制成本 | 只乘副本数,不算写流量与修复流量 |
| 何时淘汰 | 准入、热度、读保护、pin 与预算 | 删除元数据就立即复用仍在被访问的空间 |
| 如何恢复 | 元数据恢复、数据存活检查、重新注册与重建 | Master 恢复就等于全部 payload 恢复 |
| 如何降级 | 有界重试、其他副本、重算、背压 | 缓存故障时所有请求一起无限回源 |
4. 预算不能只算对象字节
至少分别估算 payload、副本、allocator 浪费、对象元数据、连接/注册资源、在途 buffer 和恢复余量。小对象很多时,目录查询和元数据可能先于网络带宽成为瓶颈。
例如 1 GiB 对象放两份,payload 至少占 2 GiB;读取者的目标 buffer、写者暂存和传输在途空间还要另算。具体能否复用同一块内存,取决于所有权和完成协议。
5. 再看实现案例
| 入口 | 重点 |
|---|---|
| Mooncake Store 概览 | Master、Client、Store 与 TE 的职责 |
| 对象内核与源码 | PutStart/PutEnd、Get、租约、副本、分配、淘汰和 HA |
| 架构与状态图 | 控制面与数据面,正常与失败路径 |
| 上层接入 | 原生 Store、分层控制器、独立缓存服务的组合边界 |
| LMCache 后端契约 | adapter 怎样把缓存生命周期映射到共享存储 |
这里的 LMCache 和 Store 资料用于对照上下层契约,不把二者当作同层替代产品。传输过程的 buffer 注册、完成和设备可见性继续看数据传输。
6. 验收
画一条成功写入和一条写者中途退出的路径;解释副本、租约、TTL 与 pin 的区别;设计“查到位置后节点退出”的处理;给出含元数据和在途空间的容量表。