在不同主机上具有重复缓存条目的分布式缓存

Distributed cache with duplicate cache entries on different host

假设我有一组内存缓存服务器,内存缓存客户端将确保缓存条目仅在单个内存缓存服务器上,并且所有客户端将始终向该服务器请求缓存条目...对吗?

现在考虑两种情况:
[1] web 服务器收到大量不同的请求(不同的 url),然后缓存条目将分布在内存缓存服务器中,请求将扇出到内存缓存集群。
在这种情况下,在单个服务器上保留单个缓存条目的内存缓存策略有效。

[2] 网络服务器收到大量对同一资源的请求,然后来自网络服务器的所有请求都将落在一个不需要的内存缓存服务器上。

我要找的是分布式缓存,其中:
[1] 每个网络服务器都可以指定使用哪个缓存节点来缓存内容。
[2] 如果任何 web 服务器使缓存无效,则缓存服务器应从所有缓存节点使其无效。
内存缓存可以满足这个用例吗?

PS:我没有大量资源可以缓存,但我有少量资源,而且有大量流量同时请求一个资源。

Memcache 是一个很棒的分布式缓存。要了解值的存储位置,最好将 memcache 集群视为一个 hashmap,每个 memcached 进程恰好是 hashmap 中的一个鸽子洞(当然每个 memcached 也是一个 'inner' hashmap,但是这对这一点并不重要)。例如,内存缓存客户端使用以下伪代码确定内存缓存节点:

index = hash(key) mod len(servers)
value = servers[index].get(key)

这就是客户端总能找到正确服务器的方法。它还强调了散列函数的重要性以及密钥的生成方式——糟糕的散列函数可能无法在不同的服务器上均匀分布密钥……。不过,默认的哈希函数几乎在任何实际情况下都能正常工作。

现在你在问题 [2] 中提到了资源请求是非随机的,特别是偏爱一台或几台服务器的情况。如果是这样的话,各个节点确实可能会收到更多的请求,但这是相对的。根据我的经验,memcache 每秒能够处理的请求数量 大大 多于您的 Web 服务器。 It easily handles 100's of thousands of requests per second on old hardware。因此,除非您的 Web 服务器比内存缓存服务器多 10-100 倍,否则您不太可能遇到问题。即使那样,您也可以通过升级单个节点以拥有更多 CPU 或更强大的 CPU 来解决问题。

但让我们假设最坏的情况 - 您仍然可以通过以下方式使用内存缓存实现此目的:

  • 将每个内存缓存安装为单个服务器(即不作为分布式缓存)
  • 在您的 Web 服务器中,您现在负责管理与每个服务器的连接
  • 您还负责确定 将每个 key/value 传递给哪个 memcached 进程,以实现目标 1
  • 如果网络服务器检测到缓存失效,它应该循环遍历使每个缓存失效的服务器,从而实现目标 2

我个人对此持保留意见 - 根据规范,您禁用了缓存的分布式方面,而分布式是该服务的一项关键功能和优势。此外,您的应用程序代码将开始需要了解各个缓存服务器,以便能够以不同的方式对待每个缓存服务器,这在体系结构上是不可取的,并且会引入大量新的配置点。

任何分布式缓存的想法都是从客户端删除位置 (*) 的所有权。正因为如此,分布式缓存和DB不允许客户端指定写入数据的服务器。

总而言之,除非您的系统期望每秒处理 100,000k 或更多请求,否则您在实践中是否会遇到此特定问题值得怀疑。如果这样做,请扩展硬件。如果这不起作用,那么您将在 memcache 上编写自己的分发逻辑、复制、刷新和管理层。我只会在真的、真的有必要的时候这样做。有一个 old saying in software development:

There are only two hard things in Computer Science: cache invalidation and naming things.

--Phil Karlton


(*) 一些分布式缓存复制条目以提高性能和(另外)在服务器出现故障时的弹性,因此数据可能同时位于多个服务器上