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

14 KiB
Raw Blame History

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 (命名空间):

// 类似 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 (内联向量):

// 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

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 (命名空间)

// 创建 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

// 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

// 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 映射:

// 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 查询:

// 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 设计

// 定义 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: 数据导出

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: 数据导入

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