#version #version-control #git #rocksdb #leveldb

已删除 ovr-vsdb

版本化状态数据库,主要用于区块链场景

1 个不稳定发布

0.34.3 2022年6月30日

#28 in #leveldb

MIT 和可能 GPL-3.0

540KB
15K SLoC

GitHub top language Latest Version Rust Documentation GitHub Workflow Status Minimum rustc version

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