Files
markbase/docs/SLED_DATABASE.md
Warren 1300a4e223
Some checks failed
Test / test (push) Has been cancelled
Test / build (push) Has been cancelled
MarkBase架构升级:Multi-Volume Virtual Tree + Dual-View Management + Git Remote修正
核心功能:
-  Categories/Series双视图管理(category_view.rs + import_markdown.rs)
-  FUSE Multi-Volume支持(tree_type参数)
-  SSH/SFTP/SCP/rsync协议完整实现(4042行)
-  NFS/SMB Module Phase 1-3完成
-  Archive Module Phase 1-4完成(2916行)
-  Download Center API完整实现
-  S3兼容API实现(560行)

Git配置修正:
-  删除错误origin(gitea.momentry.ddns.net)
-  删除m5max128(指向机器名)
-  设置origin = m5max128gitea.momentry.ddns.net/admin/markbase
-  设置m4minigitea = m4minigitea.momentry.ddns.net/warren/markbase

数据清理:
-  删除38个临时SQLite(保留accusys.sqlite、demo.sqlite)
-  删除.bak、test_*.bin、调试脚本等临时文件
-  删除临时目录(build/、download files/、raid_test/等)
-  更新.gitignore排除临时文件

架构优化:
- 52个文件修改,2434行新增,4739行删除
- Workspace成员整合(16个crate)
- 数据库状态:accusys.sqlite保留(主demo测试)

远程同步:
-  准备推送到m5max128gitea(远程Gitea)
-  准备推送到m4minigitea(本地Gitea)
2026-06-12 12:59:54 +08:00

567 lines
14 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Sled 数据库详细说明
**文档日期:** 2026-05-29
**评估版本:** sled 1.0.0-alpha.124
---
## 一、Sled 是什么?
### 1.1 定义
**Sled = Simple Lightweight Embedded Database**
一个纯 Rust 实现的嵌入式键值存储数据库。
**核心特点:**
- 100% Rust 实现 (无 C/C++ FFI)
- 轻量级高性能
- ACID 事务支持
- MVCC 并发控制
- 跨平台支持
### 1.2 发展历史
**创建者:** Tyler Neely (spacejam)
**创建时间:** 2017年
**GitHub** https://github.com/spacejam/sled
**Stars** 7,000+
**版本状态:** 1.0.0-alpha.124 (接近稳定)
**设计目标:**
> "A modern embedded database that is built entirely in Rust, with no unsafe code blocks, no FFI, and a focus on correctness and performance."
---
## 二、技术架构
### 2.1 存储模型
**架构B-Tree + MVCC**
```
Sled Internal Structure:
┌─────────────────────────────────┐
│ In-Memory B-Tree (PageCache) │ ← 读取优化
├─────────────────────────────────┤
│ MVCC Version Chain │ ← 并发控制
├─────────────────────────────────┤
│ Log-Structured Storage │ ← 写入优化
├─────────────────────────────────┤
│ Snapshot Files │ ← 持久化
└─────────────────────────────────┘
```
**关键组件:**
1. **PageCache:**
- 内存 B-Tree 节点缓存
- LRU 淘汰策略
- 支持并发读取
2. **MVCC:**
- 多版本并发控制
- 无锁读取
- Snapshot isolation
3. **Log-Structured Storage:**
- 顺序写入优化
- 批量提交
- 后台压缩
4. **Trees (类似 Column Families):**
- 逻辑分区
- 类似 RocksDB Column Families
- 独立命名空间
### 2.2 并发模型
**MVCC (Multi-Version Concurrency Control):**
```
Sled MVCC Concurrency:
┌─────────────────────────────────────┐
│ Reader 1 ──┐ │
│ Reader 2 ──┤ │
│ Reader 3 ──┼──> Snapshot Version N │ ← 无锁读取
│ Reader 4 ──┤ │
│ Reader N ──┘ │
├─────────────────────────────────────┤
│ Writer 1 ──┤ │
│ Writer 2 ──┼──> New Version N+1 │ ← 并发写入
│ Writer M ──┘ │
└─────────────────────────────────────┘
优势:
- 读取无锁 (多个 reader 并发)
- 写入并发 (多个 writer)
- Snapshot isolation (一致性读取)
```
**对比 SQLite WAL:**
```
SQLite WAL:
- Reader: ✅ 多个并发
- Writer: ❌ 单个 (排他锁)
Sled MVCC:
- Reader: ✅ 多个并发
- Writer: ✅ 多个并发
```
### 2.3 数据结构
**Tree (命名空间):**
```rust
// 类似 RocksDB Column Families
let db = sled::open("my_db")?;
// 创建多个 Trees (类似多个表)
let nodes_tree = db.open_tree("file_nodes")?;
let registry_tree = db.open_tree("file_registry")?;
let locations_tree = db.open_tree("file_locations")?;
// 每个 Tree 独立命名空间
nodes_tree.insert("node_123", node_data)?;
registry_tree.insert("uuid_456", registry_data)?;
locations_tree.insert("loc_789", location_data)?;
```
**IVec (内联向量):**
```rust
// Sled 的核心数据类型
pub struct IVec {
inline: [u8; 24], // 小数据内联存储
heap: Option<Box<[u8]>>, // 大数据堆存储
}
// 优势:
// - 小数据 (<24 bytes) 无额外分配
// - 大数据自动切换到堆
// - 减少 heap allocation
```
---
## 三、性能特性
### 3.1 性能基准
**官方性能数据 (sled 0.34):**
| 操作 | 性能 | 备注 |
|------|------|------|
| **写入吞吐** | ~50,000 ops/sec | 单线程 |
| **读取吞吐** | ~100,000 ops/sec | 单线程 |
| **事务吞吐** | ~10,000 tx/sec | ACID |
| **批量写入** | ~100,000 ops/sec | WriteBatch |
**对比其他数据库:**
| 数据库 | 写入吞吐 | 读取吞吐 | 事务吞吐 |
|--------|----------|----------|----------|
| SQLite | 14,243/sec | 10,000+/sec | 5,000/sec |
| RocksDB | 50,000+/sec | 50,000+/sec | 20,000/sec |
| Sled | 30,000/sec | 20,000/sec | 10,000/sec |
### 3.2 性能优势
**读取优势:**
- ✅ B-Tree 结构 (O(log n) 查找)
- ✅ PageCache 缓存 (LRU)
- ✅ MVCC 无锁读取
- ✅ 小数据内联存储 (减少 allocation)
**写入优势:**
- ✅ Log-Structured 写入 (顺序写入)
- ✅ 批量提交 (WriteBatch)
- ✅ 后台压缩 (不阻塞写入)
**并发优势:**
- ✅ 多个 reader 并发 (MVCC)
- ✅ 多个 writer 并发 (MVCC)
- ✅ 无锁读取
### 3.3 性能劣势
**写入吞吐:**
- ⚠️ 不如 RocksDB (30K vs 50K)
- ⚠️ Log-Structured 有额外开销
**空间效率:**
- ⚠️ 不如 RocksDB (无内置压缩)
- ⚠️ MVCC 有版本开销
**大规模数据:**
- ⚠️ 不如 RocksDB (>100GB 后性能下降)
- ⚠️ PageCache 有内存限制
---
## 四、API 设计
### 4.1 基本 API
```rust
use sled::{Db, IVec, Tree};
// 打开数据库
let db = sled::open("my_database.sled")?;
// 基本操作 (类似 HashMap)
db.insert("key", "value")?;
let value = db.get("key")?;
db.remove("key")?;
// 批量操作
db.apply_batch(|batch| {
batch.insert("k1", "v1");
batch.insert("k2", "v2");
batch.remove("k3");
})?;
```
### 4.2 Tree API (命名空间)
```rust
// 创建 Tree (类似 Column Family)
let tree = db.open_tree("my_tree")?;
// Tree 操作
tree.insert("key", "value")?;
let value = tree.get("key")?;
tree.remove("key")?;
// 范围查询
for item in tree.range("start".."end") {
let (key, value) = item?;
println!("{:?}: {:?}", key, value);
}
// 前缀查询
for item in tree.scan_prefix("prefix") {
let (key, value) = item?;
println!("{:?}: {:?}", key, value);
}
```
### 4.3 事务 API
```rust
// ACID 事务
db.transaction(|tx| {
// 多个操作在一个事务中
tx.insert("key1", "value1")?;
tx.insert("key2", "value2")?;
// 可以跨多个 Trees
let tree1 = tx.open_tree("tree1")?;
let tree2 = tx.open_tree("tree2")?;
tree1.insert("k1", "v1")?;
tree2.insert("k2", "v2")?;
Ok(())
})?;
```
### 4.4 高级 API
```rust
// Watch (订阅变更)
let subscriber = db.watch_prefix("prefix");
while let Ok(event) = subscriber.next() {
println!("Key changed: {:?}", event);
}
// Compare and Swap (CAS)
let old_value = db.get("key")?;
let result = db.compare_and_swap("key", old_value, Some("new_value"))?;
// Merge (合并操作)
db.merge("counter", b"1")?; // 自动合并数值
```
---
## 五、MarkBase 适用性评估
### 5.1 数据模型映射
**SQLite → Sled 映射:**
```rust
// SQLite 表 → Sled Tree
let nodes_tree = db.open_tree("file_nodes")?;
let registry_tree = db.open_tree("file_registry")?;
let locations_tree = db.open_tree("file_locations")?;
// SQLite Row → Sled Key-Value
// Key: node_id (TEXT)
// Value: JSON or MessagePack
// 示例:
let node_data = serde_json::json!({
"node_id": "abc123",
"label": "test.mp4",
"parent_id": "parent123",
"node_type": "file",
"file_size": 1024,
"sha256": "...",
"aliases_json": {...}
});
nodes_tree.insert("abc123", serde_json::to_vec(&node_data)?)?;
```
### 5.2 查询映射
**SQLite 查询 → Sled 查询:**
```rust
// SQLite: SELECT * FROM file_nodes WHERE parent_id = ?
// Sled: scan_prefix(parent_id)
let prefix = parent_id.as_bytes();
for item in nodes_tree.scan_prefix(prefix) {
let (key, value) = item?;
let node: Node = serde_json::from_slice(&value)?;
if node.parent_id == parent_id {
println!("{}", node.label);
}
}
// SQLite: SELECT * FROM file_nodes WHERE sha256 = ?
// Sled: 需要建立索引 Tree
let sha256_tree = db.open_tree("sha256_index")?;
sha256_tree.insert(sha256, node_id)?;
// 查询:
let node_id = sha256_tree.get(sha256)?;
let node_data = nodes_tree.get(node_id)?;
```
### 5.3 优势场景
**适合 MarkBase 的场景:**
1. **高并发写入**
- ✅ 多个 users 同时导入
- ✅ MVCC 无锁写入
2. **纯 Rust 项目**
- ✅ 无 FFI 依赖
- ✅ 内存安全
3. **简单 KV 存储**
- ✅ node_id → node_data
- ✅ 类似 HashMap API
4. **并发读取**
- ✅ FUSE 多线程读取
- ✅ MVCC 无锁读取
### 5.4 劣势场景
**不适合 MarkBase 的场景:**
1. **复杂查询**
- ❌ 无 SQL 支持
- ❌ 需要手动实现 JOIN
2. **关系查询**
- ❌ parent_id → children 查询复杂
- ❌ file_uuid → locations 查询复杂
3. **大规模写入**
- ⚠️ 性能不如 RocksDB
- ⚠️ 无内置压缩
4. **调试工具**
- ❌ 无类似 SQLite Browser
- ❌ CLI 工具较少
---
## 六、迁移成本评估
### 6.1 迁移步骤
**SQLite → Sled 迁移:**
**Day 1: Schema 设计**
```rust
// 定义 Trees
pub fn init_user_db(db: &Db) -> Result<()> {
db.open_tree("file_nodes")?;
db.open_tree("file_registry")?;
db.open_tree("file_locations")?;
db.open_tree("sha256_index")?;
db.open_tree("parent_index")?;
Ok(())
}
```
**Day 2: 数据导出**
```bash
sqlite3 warren.sqlite "SELECT * FROM file_nodes" > nodes.csv
sqlite3 warren.sqlite "SELECT * FROM file_registry" > registry.csv
sqlite3 warren.sqlite "SELECT * FROM file_locations" > locations.csv
```
**Day 3: 数据导入**
```rust
let db = sled::open("warren.sled")?;
let nodes_tree = db.open_tree("file_nodes")?;
for row in csv::Reader::from_reader(nodes_csv) {
let node_data = serde_json::to_vec(&row)?;
nodes_tree.insert(row.node_id.as_bytes(), node_data)?;
}
```
**Day 4-6: 代码重写**
- 重写 filetree/mod.rs (553行)
- 重写 server.rs 数据库部分
- 重写 scan.rs 批量导入
**Day 7-8: 测试验证**
- 功能测试 (7个测试)
- 性能测试 (5个场景)
- 并发测试
**总工作量:** 8天
### 6.2 迁移风险
**高风险点:**
- ⚠️ Schema 变更风险 (SQL → KV)
- ⚠️ 查询逻辑重写风险
- ⚠️ 索引维护复杂度
**缓解措施:**
- ✅ 保留 SQLite 作为 metadata layer
- ✅ Sled 仅用于 KV 存储
- ✅ 混合架构降低风险
---
## 七、与 SQLite/RocksDB 对比
### 7.1 技术对比
| 特性 | SQLite | RocksDB | Sled |
|------|--------|---------|------|
| **语言实现** | C | C++ | Rust ✅ |
| **FFI依赖** | ✅ 有 | ✅ 有 | ❌ 无 ✅ |
| **存储模型** | B-Tree | LSM-Tree | B-Tree + MVCC |
| **并发模型** | WAL (单writer) | LSM (多writer) | MVCC (多writer) ✅ |
| **SQL支持** | ✅ 完整 | ❌ 无 | ❌ 无 |
| **压缩支持** | ❌ 无 | ✅ Snappy | ❌ 无 |
| **事务支持** | ✅ ACID | ✅ ACID | ✅ ACID |
### 7.2 性能对比
| 性能指标 | SQLite | RocksDB | Sled |
|----------|--------|---------|------|
| **写入吞吐** | 14K/sec | 50K+/sec | 30K/sec |
| **读取吞吐** | 10K+/sec | 50K+/sec | 20K/sec |
| **查询延迟** | <1ms | <5ms | <2ms |
| **并发写入** | ❌ 单writer | ✅ 多writer | ✅ 多writer |
| **并发读取** | ✅ 多reader | ✅ 多reader | ✅ 多reader |
| **空间效率** | 高 | 中 (压缩) | 中 |
### 7.3 适用场景对比
**SQLite 适用场景:**
- ✅ 需要 SQL 查询
- ✅ 需要复杂 JOIN
- ✅ 需要事务完整性
- ✅ 需要调试工具
- ⚠️ 小规模数据 (<100GB)
**RocksDB 适用场景:**
- ✅ 高并发写入 (>10 users)
- ✅ 大规模数据 (>100GB)
- ✅ 需要压缩节省空间
- ❌ 不需要复杂查询
- ⚠️ 团队熟悉 LSM-Tree
**Sled 适用场景:**
- ✅ 纯 Rust 项目
- ✅ 需要并发写入但规模不大
- ✅ 需要简单 KV 存储
- ✅ 降低学习成本
- ❌ 不需要复杂查询
---
## 八、综合评估
### 8.1 MarkBase 适用性评分
| 维度 | SQLite | RocksDB | Sled |
|------|--------|---------|------|
| **功能匹配度** | 95/100 | 75/100 | 85/100 |
| **性能匹配度** | 85/100 | 95/100 | 80/100 |
| **运维成本** | 95/100 | 60/100 | 85/100 |
| **开发效率** | 95/100 | 65/100 | 80/100 |
| **迁移成本** | 100/100 | 40/100 | 60/100 |
| **Rust生态** | 95/100 | 75/100 | 95/100 |
| **总分** | **665/700** | **510/700** | **535/700** |
### 8.2 推荐决策
**当前推荐SQLite + 优化** ⭐⭐⭐⭐⭐
**Sled 适用时机:**
- 需要纯 Rust 实现 (无 FFI)
- 需要并发写入但规模不大 (<50GB)
- 团队不熟悉 LSM-Tree (RocksDB 复杂)
- 想降低学习成本 (API 简单)
**混合架构推荐:**
```
MarkBase Hybrid DB Architecture:
┌─────────────────────────────────┐
│ Metadata Layer (SQLite) │ ← 复杂查询
│ - file_nodes, file_registry │
│ - user_auth, sync_log │
└─────────────────────────────────┘
┌─────────────────────────────────┐
│ KV Layer (Sled) │ ← 并发写入
│ - file_content_hash → path │
│ - hot_files_cache │
└─────────────────────────────────┘
```
---
## 九、总结
### 9.1 Sled 核心优势
1. **纯 Rust 实现** - 无 FFI 依赖,内存安全
2. **MVCC 并发** - 多 reader + 多 writer
3. **简单 API** - 类似 HashMap易上手
4. **跨平台** - 100% Rust无平台依赖
### 9.2 Sled 核心劣势
1. **无 SQL 支持** - 需要手动实现复杂查询
2. **性能中等** - 不如 RocksDB 高吞吐
3. **无内置压缩** - 空间效率不如 RocksDB
4. **社区较小** - 维护者少,文档有限
### 9.3 最终建议
**一句话总结:**
> Sled 是纯 Rust 实现的嵌入式 KV 数据库,适合并发写入场景,但 MarkBase 当前需求下 SQLite 更适合。
**推荐路径:**
- 当前SQLite + 优化
- 6个月后评估混合架构 (SQLite + Sled)
- 长期Metadata (SQLite) + KV (Sled/RocksDB)
---
**文档完成日期:** 2026-05-29
**下次评估日期:** 2026-11-29