17 个版本 (9 个重大变更)

0.10.6 2024 年 6 月 29 日
0.10.4 2023 年 7 月 7 日
0.10.3 2023 年 6 月 25 日
0.9.1 2023 年 1 月 27 日
0.2.1 2021 年 10 月 22 日

#354数据库实现

每月下载量 36
5 个crate中使用(通过 infinitree

MIT/Apache

19KB
231

Infinitree

Crates.io docs.rs Build Status MIT licensed Apache2 licensed

Infinitree 是一个版本化的嵌入式数据库,使用统一且加密的二进制大对象(blob)来存储数据。

它最适合独立写进程的使用场景,因为不支持单个树上的多个写进程。

实际上,将 Infinitree 称为数据库可能过于宽泛,因为所有持久性操作都是显式的。底层,它使用 serde 以实现灵活性和与大多数库的互操作性。

特性

  • 默认线程安全
  • 透明地处理热/温/冷存储层;目前支持与 S3 兼容的后端
  • 支持通过 Iterator 特性查询版本化数据结构,无需加载全部内容
  • 加密所有磁盘上的数据,并在使用时才解密
  • 注重性能,并允许灵活地选择性能与内存使用之间的权衡
  • 可扩展以支持自定义数据类型和存储策略
  • 易于与云工作者和 KMS 集成以实现访问控制

示例用法

use infinitree::{
    Infinitree,
    Index,
    Key,
    anyhow,
    backends::Directory,
    fields::{Serialized, VersionedMap, LocalField},
};
use serde::{Serialize, Deserialize};

#[derive(Serialize, Deserialize)]
pub struct PlantHealth {
    id: usize,
    air_humidity: usize,
    soil_humidity: usize,
    temperature: f32
}

#[derive(Index, Default, Clone)]
pub struct Measurements {
    // rename the field when serializing
    #[infinitree(name = "last_time")]
    _old_last_time: Serialized<String>,

    #[infinitree(name = "last_time2")]
    last_time: Serialized<usize>,

    // only store the keys in the index, not the values
    #[infinitree(strategy = "infinitree::fields::SparseField")]
    measurements: VersionedMap<usize, PlantHealth>,

    // skip the next field when loading & serializing
    #[infinitree(skip)]
    current_time: usize,
}

fn main() -> anyhow::Result<()> {
    let mut tree = Infinitree::<Measurements>::empty(
        Directory::new("/storage")?,
        Key::from_credentials("username", "password")?
    );

    tree.index().measurements.insert(1, PlantHealth {
        id: 0,
        air_humidity: 50,
        soil_humidity: 60,
        temperature: 23.3,
    });

    *tree.index().last_time.write() = 1;
    tree.commit("first measurement! yay!");
    Ok(())
}

版本控制

Infinitree 支持版本化数据集,类似于 Git 对文件的版本控制。

虽然某些索引字段作为快照工作(例如,Serialized<T>),并在每次提交时序列化全部内容,但可以使用例如 VersionedMap<K, V> 作为增量 HashMap。

版本化类型仅存储与当前加载状态之间的差异。

还可以根据需要恢复状态,或者为每个提交创建完全不同的数据分支。

缓存

数据始终作为对象的一部分进行移动。

该机制允许对跨多个磁盘和云存储平台的数百TB数据进行索引,同时只需同步和将一小部分数据加载到内存中。

应用程序开发者可以使用简单的策略,例如最近最少使用(LRU),来对缓存层进行细粒度控制,例如将最近查询的对象存储在本地目录中,其余的存储在S3桶中。

对象系统

Infinitree的核心是一个对象系统,它以加密的4MiB块的形式存储所有数据。对象使用256位随机标识符命名,这些标识符与内容无关。对数据进行索引并将其叠加到物理对象上是具有挑战性的问题。

在Infinitree存储模型中存在两种类型的对象,它们对存储层来说是不可区分的。

  • 索引以4MB单元加密,并支持可序列化数据结构的版本控制。
  • 存储对象独立存储和加密数据块,通过ChunkPointer定位。

在这两种情况下,访问存储数据都需要知道主密钥和对称加密密钥。

为了建立一个可信的根,使用用户名/密码组合通过Argon 2生成一个密码,Argon 2输出定位所谓的根对象,它是版本化索引树的根。

由于系统需要一些对象具有确定性的标识符,因此所有对象ID都与它们存储的数据无关。

使用ChaCha20-Poly1305 AEAD确保数据的完整性。存储对象中加密的所有数据的标签存储在ChunkPointer中,而标签则附加到所有索引对象的末尾。

请注意,虽然访问根对象需要主密钥,但内部使用多个子密钥,这意味着在存储在索引中的数据上叠加其他(例如公钥)加密方法是安全的。

有关对象系统的安全和攻击者模型的更深入概述,请参阅DESIGN.md文档。

警告

这是一款未经审查的实验性安全软件。

请不要用于关键工作负载或应用程序。

许可证

MITApache 2许可证下发布。

支持

如果您有兴趣在您的应用程序中使用Infinitree,并且希望与Symmetree Research Labs合作开发功能或实现,请联系我们

依赖项

~1.3–2MB
~41K SLoC