19 个不稳定版本

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.2 2021年11月18日

#62 in 并发


用于 4 crates

MIT/Apache

255KB
5.5K SLoC

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。

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

还可以根据使用情况选择性地恢复状态,或为每个提交创建完全不同的数据分支。

缓存

数据总是作为对象的一部分移动。

这种机制允许对跨越多个磁盘和云存储平台的数据进行索引,同时只需同步和加载一小部分数据。

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

对象系统

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

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

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

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

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

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

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

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

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

警告

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

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

许可

在MIT和Apache 2许可下发布。

支持

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

依赖关系

约12-22MB
约406K SLoC