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
255KB
5.5K SLoC
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。
版本化类型只存储与当前加载状态的差异。
还可以根据使用情况选择性地恢复状态,或为每个提交创建完全不同的数据分支。
缓存
数据总是作为对象的一部分移动。
这种机制允许对跨越多个磁盘和云存储平台的数据进行索引,同时只需同步和加载一小部分数据。
应用开发者可以使用简单的策略,例如最近最少使用(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