Commit 203cb567 authored by tgs's avatar tgs

Upload 模型仓库设计v1.txt

parent 0c2dcff6
# 基于 CDC/Xet 的模型仓库多版本管理——完整设计方案
## 一、设计目标
| 目标 | 说明 |
|------|------|
| **高效版本管理** | 支持模型文件的无限版本迭代,`git log`、`git diff`、`git tag` 等操作保持毫秒级响应 |
| **块级去重** | 文件修改后仅上传变化的数据块(约 64KB 粒度),而非整个文件 |
| **存储空间节省** | 多版本共享相同数据块,避免冗余存储 |
| **传输效率** | 上传/下载仅传输新增/变化的数据块,典型场景下速度提升 2-3 倍 |
| **向下兼容** | 同时支持原生 Git 客户端和 Xet 增强客户端 |
| **水平扩展** | 存储层和服务层均可独立扩展 |
## 二、整体架构
```
┌─────────────────────────────────────────────────────────────────────────────┐
│ 客户端层 (Client Layer) │
│ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ ┌─────────────────┐ │
│ │ git-xet │ │huggingface- │ │ Web UI │ │ MLOps 工具链 │ │
│ │ (CLI增强) │ │ cli/SDK │ │ (浏览) │ │ (MLflow/Kubeflow)│ │
│ └──────┬──────┘ └──────┬──────┘ └──────┬──────┘ └────────┬────────┘ │
└─────────┼────────────────┼────────────────┼───────────────────┼────────────┘
│ │ │ │
▼ ▼ ▼ ▼
┌─────────────────────────────────────────────────────────────────────────────┐
│ 网关与服务层 (Service Layer) │
│ ┌─────────────────────────────────────────────────────────────────────┐ │
│ │ API 网关 (Hub Gateway) │ │
│ │ 认证、鉴权、限流、路由、请求转发 │ │
│ └───────────────────────────────┬─────────────────────────────────────┘ │
│ │ │
│ ┌──────────────────────────────┼─────────────────────────────────────┐ │
│ │ ▼ │ │
│ │ ┌──────────────────────────────────────────────────────────────┐ │ │
│ │ │ 版本管理服务 (Version Manager) │ │ │
│ │ │ - 仓库创建/删除 - Commit 管理 - Tag/Branch 管理 │ │ │
│ │ └──────────────────────────────────────────────────────────────┘ │ │
│ │ │ │ │
│ │ ┌──────────────────────────┼──────────────────────────────────┐ │ │
│ │ │ ▼ │ │ │
│ │ │ ┌──────────────────────────────────────────────────────┐ │ │ │
│ │ │ │ 映射服务 (Mapping Service) │ │ │ │
│ │ │ │ - Commit → 文件清单映射 - 块哈希 → 存储位置查询 │ │ │ │
│ │ │ │ - 全局块去重查询 - 文件重建元数据管理 │ │ │ │
│ │ │ └──────────────────────────────────────────────────────┘ │ │ │
│ │ └──────────────────────────────────────────────────────────────┘ │ │
│ └─────────────────────────────────────────────────────────────────────┘ │
└─────────────────────────────────────────────────────────────────────────────┘
│ │ │
▼ ▼ ▼
┌─────────────────────────────────────────────────────────────────────────────┐
│ 存储层 (Storage Layer) │
│ │
│ ┌─────────────────────────────┐ ┌─────────────────────────────────────┐ │
│ │ 元数据仓库 (Git Repo) │ │ 内容寻址存储 (CAS) │ │
│ │ │ │ │ │
│ │ - 指针文件 (.ptr) │ │ ┌─────────────────────────────┐ │ │
│ │ - 配置文件 (config.json) │ │ │ Xorb 聚合层 │ │ │
│ │ - 模型卡片 (README.md) │ │ │ (64MB/8,192个块) │ │ │
│ │ - .gitattributes │ │ └──────────┬──────────────────┘ │ │
│ │ - 完整 Git 历史 │ │ │ │ │
│ │ │ │ ┌──────────▼──────────────────┐ │ │
│ │ 托管: GitHub/GitLab/自建 │ │ │ 数据块 (Chunks) │ │ │
│ │ │ │ │ 目标 64KB, 范围 8-128KB │ │ │
│ └─────────────────────────────┘ │ │ 标识: Blake3 MerkleHash│ │
│ │ └──────────┬──────────────────┘ │ │
│ │ │ │
│ │ ┌──────────▼──────────────────┐ │ │
│ │ │ 对象存储 (S3/MinIO/Ceph) │ │ │
│ │ │ 持久化所有数据块和元数据 │ │ │
│ │ └─────────────────────────────┘ │ │
│ │ │
│ │ LFS 桥接层 (向下兼容) │ │
│ └─────────────────────────────────────┘ │
└─────────────────────────────────────────────────────────────────────────────┘
```
## 三、核心组件详解
### 3.1 客户端 (Xet-Enabled Client)
客户端的核心职责是在 `git push` 时拦截并执行块级去重上传。
```
┌──────────────────────────────────────────────────────┐
│ Xet 客户端架构 │
├──────────────────────────────────────────────────────┤
│ ┌────────────────────────────────────────────────┐ │
│ │ Git 钩子拦截器 (pre-push) │ │
│ │ 检测 push 事件,接管大文件处理 │ │
│ └──────────────────┬─────────────────────────────┘ │
│ ▼ │
│ ┌────────────────────────────────────────────────┐ │
│ │ CDC 分块引擎 (Chunker) │ │
│ │ - 读取文件流 - GearHash 滚动哈希 │ │
│ │ - 确定块边界 - 输出可变大小块 (8-128KB) │ │
│ └──────────────────┬─────────────────────────────┘ │
│ ▼ │
│ ┌────────────────────────────────────────────────┐ │
│ │ 哈希计算与去重引擎 │ │
│ │ - Blake3 MerkleHash 计算 - 本地缓存查询 │ │
│ │ - 与服务端全局索引比对 - 识别新增块 │ │
│ └──────────────────┬─────────────────────────────┘ │
│ ▼ │
│ ┌────────────────────────────────────────────────┐ │
│ │ Xorb 聚合器 (Aggregator) │ │
│ │ 将多个小块聚合成 64MB 的 Xorb 对象 │ │
│ └──────────────────┬─────────────────────────────┘ │
│ ▼ │
│ ┌────────────────────────────────────────────────┐ │
│ │ 上传调度器 (Uploader) │ │
│ │ - 并发上传 Xorb - 断点续传 - 校验重试 │ │
│ └────────────────────────────────────────────────┘ │
└──────────────────────────────────────────────────────┘
```
**参考实现**:Hugging Face 的参考实现使用 Rust 编写,位于 [xet-core](https://github.com/huggingface/xet-core)。
### 3.2 元数据仓库 (Git Repository)
存放所有**文本形态**的元数据,保持轻量高效:
| 文件类型 | 示例 | 大小 |
|----------|------|------|
| 指针文件 | `model.safetensors.ptr` | ~200 字节 |
| 模型配置 | `config.json` | ~几 KB |
| 模型卡片 | `README.md` | ~几 KB |
| 属性配置 | `.gitattributes` | ~几十字节 |
**指针文件格式示例**(伪代码):
```
version https://xet-spec.com/v1.0
oid sha256:3b8a5921e2c... (文件内容哈希)
size 10737418240
xet_file_id xet_abc123def456
```
指针文件仅记录文件的逻辑标识(`xet_file_id`),不包含任何块级别的映射信息。真正的块映射存储在映射服务中。
### 3.3 内容寻址存储 (CAS)
CAS 是 Xet 系统的核心存储基础设施:
**核心特性**:
- **内容寻址**:所有对象通过其加密哈希进行存储和检索
- **不可变性**:内容一旦存储即不可更改
- **自动去重**:相同内容在存储级别自动去重
**存储层级**:
```
┌─────────────────────────────────────────────────────────┐
│ CAS 存储层级 │
├─────────────────────────────────────────────────────────┤
│ │
│ Level 1: 数据块 (Chunk) │
│ ├─ 大小: 8KB ~ 128KB (目标 64KB) │
│ ├─ 标识: Blake3 MerkleHash │
│ └─ 内容: 原始文件数据片段 │
│ │
│ Level 2: Xorb (聚合块) │
│ ├─ 最大大小: 64MB │
│ ├─ 最大块数: 8,192 个 │
│ └─ 作用: 减少元数据和网络开销 │
│ │
│ Level 3: Shard (碎片) │
│ ├─ 最大大小: 64MB │
│ └─ 内容: Xorb 列表 + 文件重建元数据 │
│ │
│ Level 4: 对象存储 (S3/MinIO) │
│ └─ 最终持久化层 │
│ │
└─────────────────────────────────────────────────────────┘
```
### 3.4 映射服务 (Mapping Service)
维护 **Commit → 文件 → 块列表** 的三级映射关系:
**数据模型**:
```sql
-- 仓库表
CREATE TABLE repositories (
repo_id UUID PRIMARY KEY,
repo_name VARCHAR(255) UNIQUE,
created_at TIMESTAMP
);
-- Commit 映射表
CREATE TABLE commit_mappings (
commit_hash CHAR(40) PRIMARY KEY, -- Git commit SHA
repo_id UUID REFERENCES repositories,
parent_hash CHAR(40), -- 父 commit
file_manifest_id UUID, -- 指向文件清单
created_at TIMESTAMP
);
-- 文件清单表
CREATE TABLE file_manifests (
manifest_id UUID PRIMARY KEY,
file_path VARCHAR(512),
file_size BIGINT,
xet_file_id VARCHAR(64), -- Xet 文件唯一标识
chunk_list JSONB, -- [offset, hash, size]
-- 示例: [{"offset":0, "hash":"abc...", "size":65536}, ...]
);
-- 全局块索引表 (用于去重查询)
CREATE TABLE global_chunks (
chunk_hash CHAR(64) PRIMARY KEY, -- Blake3 哈希
storage_location VARCHAR(255), -- S3 路径或 CAS 引用
size INT,
ref_count INT DEFAULT 1 -- 引用计数
);
```
**关键操作**:
1. **去重查询**:客户端上传时,将块哈希列表发送给映射服务,服务返回哪些块已存在
2. **映射注册**:新 commit 创建时,注册文件→块的映射关系
3. **文件重建**:下载时,根据 commit_hash 查询完整的块列表和存储位置
## 四、CDC 分块算法
### 4.1 算法选择:GearHash
Xet 协议规范中指定使用 **GearHash** 算法进行内容定义分块。
**核心原理**:
CDC 的关键属性是**边界稳定性**:分块边界由数据内容通过滚动哈希确定,而非固定的字节偏移量。
```
原始数据: ···AAAAAA|BBBBBBBB|CCCCCCCC|DDDDDDDD|EEEEEEEE···
chunk0 chunk1 chunk2 chunk3 chunk4
在 chunk2 中插入 "XX":
···AAAAAA|BBBBBBBB|CCCCXXCCCC|DDDDDDDD|EEEEEEEE···
chunk0 chunk1 chunk2' chunk3 chunk4
(相同) (相同) (变化) (相同) (相同)
```
**固定大小分块的问题**(对比):
```
固定大小分块 - 在 chunk2 中插入 "XX":
···AAAAAA|BBBBBBBB|CCCCXXCC|CCDDDDDD|DDEEEEEE···
chunk0 chunk1 chunk2' chunk3' chunk4'
(相同) (相同) (变化) (变化) (变化)
```
插入操作导致编辑之后的所有边界偏移,所有后续块全部失效。
### 4.2 算法参数
| 参数 | 值 | 说明 |
|------|-----|------|
| 目标块大小 | 64KB | 平衡去重粒度和元数据开销 |
| 最小块大小 | 8KB | 防止块过小导致元数据爆炸 |
| 最大块大小 | 128KB | 防止块过大降低去重效率 |
| 哈希函数 | Blake3 | 用于 MerkleHash 计算 |
| 切割条件 | `hash(window) & mask == 0` | 概率均匀,保证边界分布 |
### 4.3 Python 核心实现
```python
import hashlib
def gear_hash_chunk(data: bytes,
min_size: int = 8 * 1024,
max_size: int = 128 * 1024,
target_size: int = 64 * 1024,
mask: int = 0x0000FFFF) -> list:
"""
基于 GearHash 的 CDC 分块
使用滚动哈希 + 边界条件确定切割点
"""
chunks = []
start = 0
i = 0
h = 0
mod = 1 << 64
base = 257
while i < len(data):
# 滚动哈希更新
h = (h * base + data[i]) % mod
i += 1
# 达到最小块大小后才允许切割
if i - start >= min_size:
# 哈希匹配条件 或 达到最大块大小
if (h & mask) == 0 or (i - start) >= max_size:
chunk = data[start:i]
chunk_hash = hashlib.blake3(chunk).hexdigest()
chunks.append({
'offset': start,
'size': len(chunk),
'hash': chunk_hash,
'data': chunk
})
start = i
# 重置滚动哈希
h = 0
# 处理末尾剩余数据
if start < len(data):
chunk = data[start:]
chunks.append({
'offset': start,
'size': len(chunk),
'hash': hashlib.blake3(chunk).hexdigest(),
'data': chunk
})
return chunks
```
## 五、版本管理机制
### 5.1 版本标识体系
| 层级 | 标识方式 | 作用 | 可变性 |
|------|----------|------|--------|
| **Commit** | SHA-1 哈希 | 唯一标识一次提交的快照 | 不可变 |
| **Tag** | 语义化名称 (v1.0, v2.1) | 用户可读的版本号 | 不可变(指向固定 Commit) |
| **Branch** | 分支名 (main, dev) | 开发线标识 | 可变(指向最新 Commit) |
**映射关系**:
```
用户输入: git checkout v1.0
Git 解析: v1.0 → commit_hash = a3f2c7d9...
映射服务: commit_hash → file_manifest_id → chunk_list
CAS 存储: 根据 chunk_list 从对象存储拉取数据块
客户端: 按 offset 顺序拼接 → 完整文件
```
### 5.2 版本存储示意
```
时间线 (Commits):
────────────────────────────────────────────────────────────►
commit: a3f2c7d ←── b8e9f1a ←── c4d5e2b
│ │ │
▼ ▼ ▼
文件清单: [块A,块B,块C] [块A,块D,块C] [块A,块E,块C]
│ │ │
└────────────────────┼────────────────────┘
对象存储实际占用:
块A (复用) + 块B + 块C + 块D + 块E
(5个块 vs 3个完整文件副本)
```
**存储节省原理**:3 个版本共享块 A 和块 C,仅存储各自独有的块。
## 六、核心流程
### 6.1 上传流程(git push)
```
┌──────────┐ ┌──────────┐ ┌──────────┐ ┌──────────┐
│ 用户 │ │ 客户端 │ │ 映射服务 │ │ CAS存储 │
└────┬─────┘ └────┬─────┘ └────┬─────┘ └────┬─────┘
│ │ │ │
│ git push │ │ │
│───────────────>│ │ │
│ │ │ │
│ │ 1. 读取文件 │ │
│ │ 2. CDC分块 │ │
│ │ 3. 计算哈希 │ │
│ │ │ │
│ │ 4. 发送哈希列表 │ │
│ │───────────────>│ │
│ │ │ │
│ │ 5. 返回已存在块 │ │
│ │<───────────────│ │
│ │ │ │
│ │ 6. 仅上传新块 │ │
│ │───────────────────────────────>│
│ │ │ │
│ │ 7. 注册映射 │ │
│ │───────────────>│ │
│ │ │ │
│ │ 8. 上传指针文件 │ │
│ │ (Git原生) │ │
│ │───────────────>│ │
│ │ │ │
│ 上传完成 │ │ │
│<───────────────│ │ │
│ │ │ │
```
**关键优化**:典型的 5GB 数据库文件追加 1MB 数据,LFS 需重新上传 5GB(约 13 分钟),Xet 仅需上传变化块(约 0.1 秒)。
### 6.2 下载流程(git clone / git checkout)
```
┌──────────┐ ┌──────────┐ ┌──────────┐ ┌──────────┐
│ 用户 │ │ 客户端 │ │ 映射服务 │ │ CAS存储 │
└────┬─────┘ └────┬─────┘ └────┬─────┘ └────┬─────┘
│ │ │ │
│ git clone │ │ │
│───────────────>│ │ │
│ │ │ │
│ │ 1. 拉取元数据 │ │
│ │ (Git原生) │ │
│ │───────────────>│ │
│ │ │ │
│ │ 2. 获取指针文件 │ │
│ │<───────────────│ │
│ │ │ │
│ │ 3. 请求文件清单 │ │
│ │───────────────>│ │
│ │ │ │
│ │ 4. 返回块列表 │ │
│ │<───────────────│ │
│ │ │ │
│ │ 5. 并行下载块 │ │
│ │───────────────────────────────>│
│ │ │ │
│ │ 6. 校验哈希 │ │
│ │ 7. 按offset拼接│ │
│ │ │ │
│ 文件就绪 │ │ │
│<───────────────│ │ │
│ │ │ │
```
**性能数据**(Hugging Face 实测):
| 指标 | Git LFS | Xet (CDC) |
|------|---------|-----------|
| 平均下载时间 | 51 分钟 | 19 分钟 |
| 平均上传时间 | 47 分钟 | 24 分钟 |
| 存储占用 | 8.9 GB | 3.52 GB |
## 七、性能优化策略
### 7.1 本地缓存
客户端维护本地块缓存,已下载的块在本地保留,后续版本切换时无需重新下载。
### 7.2 并行传输
- 多线程并发下载/上传 Xorb
- 每个 Xorb 最大 64MB,包含最多 8,192 个块
### 7.3 压缩优化
Xorb 对象在存储前进行压缩,减少存储空间和传输带宽。
### 7.4 增量更新
- **上传**:仅传输新增块,已存在块直接复用
- **下载**:仅下载本地缺失的块
### 7.5 全局去重
跨文件、跨仓库的相同内容块自动去重。
## 八、安全与权限
### 8.1 数据完整性
- 每个块使用 Blake3 MerkleHash 标识
- 下载时校验哈希,确保数据完整性
- 文件重建时验证所有块的哈希匹配
### 8.2 访问控制
- 块级权限控制:用户只能读取其有权访问的文件所需的块
- 仓库级别的读写权限继承自 Hugging Face Hub
- Xet 令牌认证机制
### 8.3 隐私保护
- 块内容通过加密哈希保护
- 哈希不可逆,无法从哈希还原原始内容
## 九、部署架构
```
┌──────────────────┐
│ Load Balancer │
│ (Nginx/ALB) │
└────────┬─────────┘
┌──────────────┼──────────────┐
│ │ │
┌────▼────┐ ┌────▼────┐ ┌────▼────┐
│ API节点1│ │ API节点2│ │ API节点3│ ← 无状态,水平扩展
│ (服务层)│ │ (服务层)│ │ (服务层)│
└────┬────┘ └────┬────┘ └────┬────┘
│ │ │
└──────────────┼──────────────┘
┌──────────────┼──────────────┐
│ │ │
┌────▼────┐ ┌────▼────┐ ┌────▼────┐
│ Git │ │Postgre- │ │ Redis │
│ Server │ │ SQL │ │ (缓存) │
│(元数据) │ │(映射) │ │ │
└─────────┘ └─────────┘ └─────────┘
┌────▼────┐
│ MinIO/ │
│ S3集群 │
│(对象存储)│
└─────────┘
```
**扩展性说明**:
- **API 节点**:无状态,可根据流量水平扩展
- **PostgreSQL**:读写分离 + 分库分表
- **Redis**:缓存热点块哈希和映射关系
- **MinIO/S3**:分布式对象存储,支持 PB 级扩展
## 十、与 Git LFS 的对比总结
| 维度 | Git LFS | Xet (CDC) |
|------|---------|-----------|
| **去重粒度** | 文件级 | 块级 (8-128KB) |
| **修改 5GB 文件中的 1MB** | 重新上传 5GB | 仅上传变化的块 |
| **存储效率** | 低(每个版本存完整文件) | 高(块级共享) |
| **上传速度** | 慢(全量传输) | 快(增量传输) |
| **跨文件去重** | 不支持 | 支持 |
| **Git 原生支持** | 是(官方扩展) | 需安装 Xet 客户端 |
| **向下兼容** | 完整 | LFS 桥接层 |
## 十一、实施路线图
### Phase 1: 基础架构搭建
- [ ] 部署 CAS 存储集群(MinIO/S3)
- [ ] 部署映射服务(PostgreSQL + Redis)
- [ ] 搭建 Git 元数据仓库服务
### Phase 2: 客户端开发
- [ ] 实现 CDC 分块引擎(GearHash)
- [ ] 实现 Git pre-push 钩子拦截
- [ ] 实现 Xorb 聚合与上传调度
- [ ] 实现下载与文件重建
### Phase 3: 服务端开发
- [ ] 实现全局块去重查询 API
- [ ] 实现映射注册 API
- [ ] 实现 LFS 桥接层(向下兼容)
- [ ] 实现认证与权限控制
### Phase 4: 测试与优化
- [ ] 单元测试 + 集成测试
- [ ] 大规模性能测试(PB 级数据)
- [ ] CDC 参数调优(块大小、边界条件)
- [ ] 监控与告警体系搭建
### Phase 5: 生产部署
- [ ] 灰度发布
- [ ] 全量迁移
- [ ] 文档与开发者工具完善
\ No newline at end of file
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment