#key-value-store #cache #memory #map #graphql-server #storage #server

app mapage

基于内存的类型命名空间键值存储,支持GraphQL

2个不稳定版本

0.2.0 2024年1月25日
0.1.0 2023年8月2日

#60缓存

MIT/Apache

770KB
15K SLoC

Mapage

Mapage是一个类型命名空间键值存储系统,它使用async-graphql进行客户端交互。

“类型命名空间”的意思是每个可存储类型都拥有自己的哈希表和自己的API部分。


设计目标

  • 可定制:选择你想要存储的类型和存储它们的映射实现。
  • 易于优化:轻松找到最快结果的最佳功能。
  • 类型命名空间:错误类型应很少出现,或者在指定要存储的确切类型时几乎不存在。
  • 文件存储:轻松缓存文件。
  • 持久化:将缓存数据中任何更改存储在你选择的数据库系统或文件中。
  • 可脚本化:实现你选择的功能。
  • 可监控:轻松了解CPU和RAM使用情况。
  • 可搜索:从基本的到正则表达式再到基于向量的搜索功能。

原子性级别

命名空间-类型设计使支持不同的原子性级别相对简单。

级别 描述
存储 每次交互只能对存储执行一个操作(读取或写入)。
命名空间 每次交互只能对每个单独的命名空间执行一个操作。
子命名空间 每次交互都会锁定命名空间的某个部分(桶)。
每个值都由每个线程在单个级别上进行交互,命名空间很少或从不锁定。

从功能的角度来看,原子性级别分为两个广泛的类别

存储级别功能
store_aml
sub_store_aml

使用store_aml(存储原子性级别)时,所有数据都包含在单个同步对象中,例如Mutex或Actor,但使用sub_store_aml(子存储原子性级别)功能,你可以更自由地决定每个命名空间如何处理用户交互。

store_aml尚未实现。

一旦选择了sub_store_aml,就必须选择一个默认存储实现功能。

默认存储实现功能
scc_hashmap_namespaces
dashmap_namespaces

正如你可能推测的那样;当你选择 "scc_hashmap_namespaces" 时,默认获得 scc::Hashmap 命名空间实现;当你选择 "dashmap_namespaces" 时,默认获得 Dashmap 命名空间实现。

只选择其中之一。


所有功能

功能 描述
store_aml 存储原子性级别
sub_store_aml 子存储原子性级别
scc_hashmap_namespaces 默认使用 scc::Hashmap 命名空间实现
dashmap_namespaces 默认使用 Dashmap 命名空间实现
all_types 所有类型
char char 类型
f32 f32 类型
f64 f64 类型
i8 i8 类型
i16 i16 类型
i32 i32 类型
i64 损坏 - 与 GraphQL/async-graphql 不兼容
i128 损坏 - 与 GraphQL/async-graphql 不兼容
isize 将被移除
String String 类型
u8 u8 类型
u16 u16 类型
u32 u32 类型
u64 损坏 - 与 GraphQL/async-graphql 不兼容
u128 损坏 - 与 GraphQL/async-graphql 不兼容
usize 将被移除
任何东西 一个除了 SelectedType 之外的所有东西的 GraphQL 联合体
SelectedType 一个除了 Whatever - 将被移除之外的所有其他选择的 GraphQL 联合体
Vec_bool A std::vec::Vec of bools
Vec_char      "          chars
Vec_f32      "          f32s
Vec_f64      "          f64s
Vec_i8      "          i8s
Vec_i16      "          i16s
Vec_i32      "          i32s
Vec_i64 损坏 - 与 GraphQL/async-graphql 不兼容
Vec_i128 损坏 - 与 GraphQL/async-graphql 不兼容
Vec_isize 将被移除
VecSelectedType 将被移除
VecString A std::vec::Vec of std::string::Strings
Vec_u8      "          u8s
Vec_u16      "          u16s
Vec_u32      "          u32s
Vec_u64 损坏 - 与 GraphQL/async-graphql 不兼容
Vec_u128 损坏 - 与 GraphQL/async-graphql 不兼容
Vec_usize 将被移除
VecWhatever A std::vec::Vec of Whatevers
all_key_types_String 默认使用 std::string::String 键
all_key_types_Arc_String 默认使用包含 std::string::String 键的 std::sync::Arc

设置

待实现


构建示例

包含所有内容的示例

cargo build --features=sub_store_aml,scc_hashmap_namespaces,all_types,all_key_types_String

在上面的构建中,你有 "sub_store_aml" 功能来指示每个命名空间独立处理同步。

"scc_hashmap_namespaces" 功能表示你希望命名空间实现默认为 scc::Hashmaps。

"all_types" 功能表示你希望将支持的所有类型都包含在构建中。

最后,"all_key_types_String" 功能表示你希望所有包含类型的键默认为 std::string::Strings。


使用 all_types 功能虽然方便,但会产生一个具有巨大 GraphQL API 的 mapage 应用程序。

为什么不尝试更加有选择性呢?

cargo build --features=sub_store_aml,dashmap_namespaces,bool,char,i32,Whatever,all_key_types_String

在这里,我们使用 dashmap_namespaces 而不是 sub_store_aml 作为命名空间实现。

并且,而不是 all_types,有四个单独的类型指定:bool、char、i32 和 Whatever。


当你知道你想要存储什么时,你会避免使用不必要的空间,并且会比选择所有可用的内容具有更简洁的 API。


构建必需品

明确来说,在每个构建中,你需要或应该指定以下内容

  1. 存储原子性级别(目前只有 sub_store_aml 是有效的)
  2. 为每个选定的类型默认使用的命名空间实现。
  3. 你想要(char、f32、i8 等)的类型(这是可选的,但如果你跳过此步骤,缓存将不会很大)
  4. 每个命名空间默认使用的键类型

功能不兼容性错误条件尚未实现,因此如果您遇到错误,可能需要进行一些阅读。

最优构建

待实现


关于实验的说明

虽然您会实现最实用的最优功能,但也会添加一些次优功能以满足好奇心。


待办事项

  • 增加存储/命名空间管理功能,用于处理以下功能:
    • 对象驱逐。
    • 身份验证和授权。
    • 持久化。
    • 复制(部分和全部)。
    • 事件/流。
  • 添加子命名空间。
  • 添加不可变命名空间,其中值可以添加、检索、删除、替换,并且只有不可变方法可以调用。此外,集合也存放在Arcs中。
  • 异步-GraphQL响应缓存(可能以5秒为增量)。
  • 使用Rhai和Lua(以及其他)进行脚本编写。
  • WGPU集成 - 与脚本结合使用。
  • Arc字符串键和其他键类型。
  • 添加冲突功能规范的错误条件和消息。
  • 向量比较功能。
  • 向量搜索功能。
  • 使用类似于Moka和std::Hashmap等集合类型添加更多命名空间实现。
  • 存储和原子性级别的完整命名空间实现。
  • 添加正则表达式存储。
  • 添加使用正则表达式搜索命名空间项的功能,该正则表达式可以是存储的或请求的一部分,即基于正则表达式是否匹配进行大量删除等。
  • 添加基于是否以特定值序列开始或结束或包含该值序列删除命名空间项的功能。
  • 清理代码。
  • 编写代码文档。

可能的

  • 选项类型(除非是Vec>)。

已知问题及要删除或禁用的类型。

功能 问题
i64 损坏 - 与 GraphQL/async-graphql 不兼容
i128 损坏 - 与 GraphQL/async-graphql 不兼容
isize 将被移除
u64 损坏 - 与 GraphQL/async-graphql 不兼容
u128 损坏 - 与 GraphQL/async-graphql 不兼容
usize 将被移除
SelectedType 除了Whatever之外,选择所有其他选择的GraphQL联合 - 将被删除/禁用。
Vec_i64 损坏 - 与 GraphQL/async-graphql 不兼容
Vec_i128 损坏 - 与 GraphQL/async-graphql 不兼容
Vec_isize 将被移除
VecSelectedType 将被删除/禁用。
Vec_u64 损坏 - 与 GraphQL/async-graphql 不兼容
Vec_u128 损坏 - 与 GraphQL/async-graphql 不兼容
Vec_usize 将被移除

因此,GraphQL不支持大于32位的整数。

我将为这个问题实现一个解决方案。

isize和usize类型是多余的。

SelectedType是为了异步查询实验而实现的。

我认为我进入了这个功能的试验实现阶段,我可能会重新访问它,所以我将在下一个版本中删除SelectedType和VecSelectedType,但会保留代码在存储库中。


关于泛型排列

为了控制所需工作量,某些类型的类将实现或不会实现。

  • 没有选项,除非在其他泛型中,例如Vec>。虽然使用基本级别的Option可以在命名空间中保留键,但至少目前,基本级别的Option命名空间不会添加。
  • 由于hashmaps和其他接受多个参数的泛型类型可以有多种组合,因此命名空间实现的键可能将限制为可用功能的选择,而不是任意值(子命名空间)。

自2022年中期作为Redis-like缓存启动以来,该项目已经取得了很大的进展,但仍有很多工作要做。请使用时请理解,该项目是一个持续进行中的项目。


编码风格

本项目的编码风格强调使用空白空间,而不是保持行和列数低。

所以这个

fn foo()
{

    bar();

}

不是这个

fn foo()
{
    bar();
}


许可

根据以下之一许可:

由您自行决定


贡献

请克隆仓库,并创建一个issue,解释您想添加哪些功能或修复哪些bug,以及您打算如何实现这些添加或修复。尽管不需要详尽无遗,但请尽量提供详细信息,我们将据此进行下一步操作(取决于可用性)。


除非您明确指出,否则您按照Apache-2.0许可定义提交的任何有意包含在作品中的贡献,应按上述方式双重许可,无需任何额外条款或条件。

依赖项

~24–37MB
~677K SLoC