#cache #distributed #memcached #grpc #shard #replace #key-prefix

groupcache

groupcache 是一个分布式缓存和缓存填充库,在很多情况下可作为 memcached 节点池的替代品。它通过键进行分片以选择哪个节点负责该键。

3 个不稳定版本

0.2.1 2024年3月5日
0.2.0 2024年3月5日
0.1.0 2023年11月26日

#166 in 缓存

MIT 许可证

70KB
1K SLoC

groupcache

Crates.io Documentation Codecov Dependency status License: MIT

这是将一个流行的分布式缓存库从 Go groupcache 转移到 Rust 的实现。

groupcache 是一个分布式缓存和缓存填充库,在很多情况下可作为 memcached 节点池的替代品。它通过键进行分片以选择哪个节点负责该键。

与原始实现比较

  • 使用 Rust 实现,因此速度非常快。但实际上,我还没有进行过任何严肃的基准测试。
  • 没有实现分组(这使得我怀疑 groupcache 的名字是否仍然有意义)。
    • 如果需要这样的功能,可以通过在库的顶部实现不同的 ValueLoader 实现,根据键前缀来实现。
    • 然而,在这种情况下,所有指标都会一起汇总,并且无法针对每个组进行缓存定制。这可能是未来版本中需要考虑的事情。
  • 内置服务发现机制
  • 支持缓存失效
    • 必须小心处理来自 hot_cache 的过时值,请参阅 GroupcacheBuilder 的文档。

与 memcached 的比较(来自原始仓库)

与 memcached 一样,groupcache

通过键进行分片以选择哪个节点负责该键。与 memcached 不同,groupcache

  • 不需要运行一组单独的服务器,从而大幅减少了部署/配置的痛苦。groupcache 既是客户端库也是服务器。它连接到自己的节点,形成一个分布式缓存。

  • 还提供缓存填充机制。而 memcached 只会说“抱歉,缓存未命中”,通常会导致来自无界数量的客户端(这已导致几次有趣的故障)的数据库(或任何其他)负载,而 groupcache 协调缓存填充,以确保整个复制进程集中只有一个进程加载缓存,然后将加载的值多路复用到所有调用者。

  • 不支持版本化值。如果键 "foo" 的值是 "bar",则键 "foo" 必须始终是 "bar"。没有缓存过期时间,也没有显式缓存淘汰。因此,也没有 CAS(比较并交换)操作,也没有增量/减量操作。这也意味着 groupcache...

  • ...支持将超级热项自动镜像到多个进程中。这可以防止因非常流行的键/值而导致的 memcached 热点问题,即机器的 CPU 和/或 NIC 被过载。

  • 目前仅适用于 Go。我不太可能将其代码移植到任何其他语言。

加载过程

简而言之,对 Get("foo") 的 groupcache 查找过程如下

(在运行相同代码的 N 台机器中的一台机器 #5 上)

  • "foo" 的值是否在本地内存中,因为它是超级热项?如果是,则使用它。

  • "foo" 的值是否在本地内存中,因为 peer #5(当前 peer)是它的所有者?如果是,则使用它。

  • 在我的一组 N 个 peer 中,我是键 "foo" 的所有者吗?(例如,它是否一致性哈希到 5?)如果是,则加载它。如果有其他调用者通过相同的进程或通过来自 peers 的 RPC 请求进入,它们将阻塞等待加载完成并获得相同的答案。如果不是,则 RPC 到所有者的 peer 并获取答案。如果 RPC 失败,则直接在本地加载(仍然带有本地重复抑制)。

示例

  • simple - 展示了 groupcache 如何去重并发请求。
  • simple-multiple-instances - 展示了 groupcache 如何与多个实例连接。
  • kubernetes-service-discovery - 展示了如何在 k8s 上部署简单的 axum 服务器的同时运行 groupcache。服务发现通过集成 Kubernetes API 服务器来处理。

文档

请参阅 https://docs.rs/groupcachehttps://docs.rs/groupcache/latest/groupcache/struct.Groupcache.html

依赖关系

~12–21MB
~284K SLoC