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)
19KB
231 行
Infinitree
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文档。
警告
这是一款未经审查的实验性安全软件。
请不要用于关键工作负载或应用程序。
许可证
支持
如果您有兴趣在您的应用程序中使用Infinitree,并且希望与Symmetree Research Labs合作开发功能或实现,请联系我们。
依赖项
~1.3–2MB
~41K SLoC