#key-value-store #transactional #type-safe #persistent #optimized #log #read

hmdb

类型安全、读取优化、事务性、持久化、内存中、键值存储

18 个版本

0.2.2 2022 年 9 月 21 日
0.2.1 2022 年 9 月 20 日
0.1.14 2022 年 9 月 13 日
0.1.13 2022 年 8 月 6 日
0.1.0 2022 年 3 月 30 日

1814数据库接口

每月 35 次下载

BSD-3-Clause

24KB
472

非常初稿,只是记录了一些想法。

hmdb

具有以下属性的嵌入式数据库:

  • 读取优化
  • 持久化
  • 事务性
  • 内存中
  • 键值存储
  • Rust 中定义并强制执行模式

将一组特质应用于适当的结构,允许并发访问一组 HashMap。写入通过只追加日志写入磁盘。日志可以通过快照进行压缩。快照是原子写入的,日志的追加是有限范围的,如果它们损坏。压缩可以在单独的线程上自动发生,或者当应用程序认为这是合适的时候。数据库可以配置为不同的一致性保证(缓冲日志)并且可以配置为在多个非协作进程共享数据目录的环境中(文件锁+无日志缓冲区)。优化延迟和紧凑的磁盘格式。

您对模式的所有知识,您都可以在编译时表达给数据库。您可以在 Rust 中指定哪些表存在以及这些表有什么键和值。数据库支持实现 serde 特质的任何内容,并使用 bincode 作为磁盘格式(经过战斗测试的性能和紧凑性的局部优化)。无需自己管理映射到和从数据库特定类型。

目标用途

定义模式

schema! {
    SchemaV1 {
        accounts: <Username, Account>,
        files: <Uuid, EncryptedFileMetadata>
    }
}

在底层,这将生成结构 SchemaV1,您可以使用它这样做

fn main() {
    let db = SchemaV1::init("data.db");
}

SchemaV1 是您的类型,但它将具有从该包中实现的各种特质。这些特质包括 Initialize,它允许您从磁盘启动数据库,初始化将使用代表您的 OnDiskFormat 的关联类型。

您可以直接与您的表交互

fn main() {
    let db = SchemaV1::init("data.db");

    db.accounts.insert(Username::from("parth"), Account { ... });
    let account = db.accounts.get(Username::from("parth"));

    db.files.insert(meta.id, meta);
    let file = db.files.get(meta.id);
}

这些类型不是基于使用隐式推断的,您在表示模式的一个位置中指定它们。

如果您想演变您的模式,您会这样做

schema! {
    SchemaV1 {
        accounts: <Username, Account>,
        files: <Uuid, EncryptedFileMetadata>
    }
}

schema! {
    SchemaV2 {
        accounts: <Username, AccountV2>,
        files: <Uuid, EncryptedFileMetadata>
    }
}

fn main() {
    let old = SchemaV1::init("data.db");
    let new = SchemaV2::init("data-v2.db");

    old.accounts
        .iter()
        .map(|key, value| new.accounts.insert(key, value.into()));

    old.files
        .iter()
        .map(|key, value| new.files.insert(key, value.into()));

    // Migration successful, safe to delete data.db
}

基本事务体验

schema! {
    SchemaV1 {
        accounts: <Username, Account>,
        files: <Uuid, EncryptedFileMetadata>
    }
}

fn main() {
    let db = SchemaV1::init("data.db");

    db.transaction(|accounts, files| {});
}

最基本和最原始的版本将仅锁定一切以进行事务处理。更高级的实现可以允许您指定要锁定的表。长期目标状态可能涉及无锁和一些乐观并发。

虽然这已经预期在使用lockbook时会显著提高速度,但通过实验最先进的状态可以获得更多收益

依赖项

约1–1.7MB
约35K SLoC