6

我们有一个梦幻足球应用程序,它使用 memcached 和经典的 memcached-object-read-with-sql-server-fallback。这工作得很好,但最近我一直在考虑所涉及的开销以及这是否是最好的方法。

举个例子——我们需要生成一个用户团队的下拉列表,所以我们遵循这个模式:

  1. 从 memcached 获取用户团队列表
  2. 如果不可用,则从 SQL 服务器获取列表并存储在 memcached 中。
  3. 执行 multiget 以获取团队对象。
  4. 回退到从 sql 加载对象存储这些。

这一切都很好 - 每条缓存的数据都相对容易缓存和失效,但这有两个主要缺点:

1) 因为我们正在对对象进行操作,所以会产生相当大的开销——单个团队在 memcached 中占用数百字节,而我们真正需要的是团队名称和 id 列表——而不是所有其他的东西团队对象。

2) 由于加载单个对象的回退,在空缓存上或项目过期时生成的 SQL 查询的数量可能很大:1 x Memcached multiget(未命中,哪个和原因)1 x SELECT ... FROM Team WHERE Id IN (...) 20 x Store in memcached 所以这是 21 个网络请求仅针对这个查询,而且 IN 查询比特定连接慢。

显然我们可以做一个简单的

SELECT Id, Name FROM Teams WHERE UserId = XYZ

并缓存该结果,但这意味着每当用户创建新团队时,都需要专门使这些数据无效。在这种情况下,它可能看起来相对简单,但我们有许多此类查询,其中许多操作在不容易失效的轴上(例如您的朋友在特定游戏)。

Sooo ..我的问题是 - 你们中的任何人有解决上述缺点的想法吗,还是我应该接受存在开销并且缓存未命中是不好的,忍受它?

4

2 回答 2

0

关于缓存:

您通常使用缓存来卸载较慢的基于磁盘的存储,在本例中为 mysql。内存缓存很容易扩展,mysql 扩展不太容易。

鉴于此,即使您将缓存的 cpu/网络工作/内存使用量加倍并再次将它们放在一起,它仍然会卸载 db。添加另一个 nodejs 实例或另一个 memcached 服务器很容易。

回到你的问题

  1. 您说它是用户的团队,您可以在用户登录时去获取它,并在用户在整个会话期间更改它时将其更新在缓存中。

  2. 我假设团队成员的名字不会改变,如果是这样,您可以通过 id、name 加载所有团队成员并将它们存储在缓存中,甚至在 nodejs 上本地,使用与现在相同的后备策略。然后只剩下第 1 步、第 2 步和第 4 步。

就我个人而言,我通常会尝试将 sql 结果拆分为较小的现成片段并缓存它们,并尽可能长时间地保持缓存更新,不合时宜地尝试将 mysql 仅用作存储而从不从中读取

通常,无论如何,您都会对从 mysql 返回的行运行一些逻辑,无需继续重复。

于 2013-12-17T22:06:45.817 回答
0

首先,缓存你需要的东西,也许那两个字段,不是一个完整的记录。

二、把需要的东西再缓存一次,把结果集打成记录,分别缓存

于 2013-03-27T02:18:10.033 回答