1 个不稳定发布
0.34.3 | 2022年6月30日 |
---|
#28 in #leveldb
540KB
15K SLoC
VSDB
VSDB 是一种以键值数据库形式的 'Git'。
基于VSDB强大的版本控制功能,您可以轻松地使您的数据结构具有版本管理能力。
让一切都有版本!
亮点
- 支持类似于Git的版本操作,例如
- 创建无数分支并将它们合并到父分支
- 将 '分支' 回滚到指定的历史 '版本'
- 在指定的 '分支' 上查询键的历史值
- 大多数API与标准库中相应的数据结构类似
- 使用
Vecx
就像使用Vec
- 使用
Mapx
就像使用HashMap
- 使用
MapxOrd
就像使用BTreeMap
- 使用
- ...
示例
假设您有一个像这样的出色算法
struct GreatAlgo {
a: Vec<...>,
b: BTreeMap<...>,
c: u128,
d: HashMap<...>,
e: ...
}
只需用相应的VSDB数据结构替换原始结构,您的算法就能立即获得强大的版本控制能力!
#[dervive(Vs, Default)]
struct GreatAlgo {
a: VecxVs<...>,
b: MapxOrdVs<...>,
c: OrphanVs<u128>,
d: MapxVs<...>,
e: ...
}
let algo = GreatAlgo::default();
algo.get_by_branch_version(...);
algo.branch_create(...);
algo.branch_create_by_base_branch(...);
algo.branch_create_by_base_branch_version(...);
algo.branch_remove(...);
algo.version_pop(...);
algo.prune();
注意!!
该 #[derive(Vs)]
宏可以应用于内部字段全部为VSDB中定义的类型(原始类型及其集合也受支持)的结构,但不能应用于VSDB类型之间的嵌套包装器,如果您确实需要这些功能(更好的性能),我们建议您使用多键API,或者您将不得不手动实现 VsMgmt
特性。
此数据结构可以正确处理 #[derive(Vs)]
#[derive(Vs)]
struct GoodCase<K, T> {
a: VecxVs<i64>,
b: SubItem0,
c: SubItem1,
d: SubItem2,
e: u8,
f: Vec<i16>,
g: VecDeque<i64>,
h: BTreeSet<u16>,
i: HashMap<K, AtomicU64>,
j: HashSet<i32>,
k: LinkedList<()>,
l: Box<dyn AsRef<bool>,
m: Box<dyn AsRef<[Vec<u128>]>>,
n: PhantomData<T>,
}
#[derive(Vs)]
struct SubItem0(MapxVs<u8, u8>, VecxVs<u8>);
#[derive(Vs)]
struct SubItem1 {
a: OrphanVs<i16>,
b: MapxOrdVs<String, u8>
}
#[derive(Vs)]
struct SubItem2 {
a: i8,
b: u128
}
// // A nope implementation of `VsMgmt` for custom stateless types.
// // the `#[derive(Vs)]` on 'SubItem2' is same as this implementation.
// impl VsMgmt for SubItem2 {
// impl_vs_methods_nope!();
// }
但是 此结构无法正确处理 #[derive(Vs)]
// It can be compiled, but the result is wrong !
// The versioned methods of the inner 'MapxVs<u8, u8>' will missing,
// We recommend you to use the 'multi-key' APIs of VSDB, or
// you will have to implement the 'VsMgmt' trait manually.
#[derive(Vs)]
struct BadCase {
a: VecxVs<MapxVs<u8, u8>>,
}
请检查多键函数,如果您有上述或类似场景的需求。
一些完整的示例
编译功能
- [默认]
sled_engine
,使用 sled 作为后端数据库- 更快的编译速度
- 版本化函数中的运行速度更快
- 支持编译成静态链接对象
rocks_engine
,使用 rocksdb 作为后端数据库- 非版本化函数中的运行速度更快
- 不能编译成静态链接对象
- [默认]
msgpack_codec
,使用 msgpack 作为编解码器- 运行速度更快
bcs_codec
,使用 bcs 作为编解码器- 由 Facebook 的 'Libre' 项目创建
- 针对区块链场景的安全增强
- [默认]
derive
,启用Vs
过程宏 merkle
,启用可选的梅克尔树实现compress
,在后端数据库中启用压缩hash
,启用可选的哈希函数- 基于 'blake3' crate
底层设计
基于底层的一维线性存储结构(原生 kv 数据库,如 sled/rocksdb 等),划分多个不同的命名空间,然后在这些划分的命名空间基础上,抽象多维逻辑结构中的每个维度。
在 kv 数据库类别中,命名空间可以表示为不同的键范围,或不同的键前缀。
这就像在计算机内存中表示复杂的数据结构(内存本身只是一维线性结构)一样。
用户数据将分为两个维度:“分支”和“版本”,'基本'类别的函数是无状态的,而'版本化'类别的函数是有状态的。在内部实现中,每个有状态的函数都是基于其对应的无状态函数实现的,所有有状态数据都有两个额外的标识维度('分支'和'版本'),类似于 Git 中的逻辑。无状态函数没有'版本'管理功能,但它们具有更高的性能。
注意
- VSDB 实例的序列化结果不能用作分布式一致性的基础
- 序列化结果仅包含一些元信息(存储路径等)
- 这些元信息在不同环境中可能不同
- 正确的方法是从中读取所需的内容,然后处理实际内容
- 版本名称必须是全局唯一的
- 在不同分支上使用相同的版本名称也是不允许的
依赖项
~1-11MB
~139K SLoC