20

我一直在研究缓存(主要是 redis 和 memcached),并且很难弄清楚当您的数据不断变化时在哪里使用缓存。

以 Twitter 为例(请阅读让 Twitter 速度提高 10000%)。当大部分数据库记录不断变化时,您(或他们)将如何缓存他们的数据?

假设 Twitter 有这些模型:User, Tweet, Follow, Favorite.

有人可能会发布一条一天被转发一次的推文,而另一条一天被转发一千次的推文。对于那 1000 次转推,由于24 * 60 == 1440一天中大约有几分钟,这意味着推文几乎每分钟都会更新(比如说它也有 440 个收藏夹)。跟关注一个人一样,charlie sheen 甚至在 1 天内就吸引了 100 万 Twitter 关注者。在这些情况下缓存似乎不值得,但可能只是因为我还没有达到那个水平。

还要说,平均 Twitter 追随者每天至少发一次推文/关注/收藏。这意味着在幼稚的 intro-rails 模式案例中,用户表每天至少更新一次(tweet_count等)。这种情况对于缓存用户配置文件很有意义。

但是对于上面的 1000x 推文和 100 万关注者的例子,在缓存数据方面有哪些推荐的做法?

具体来说(假设 memcached 或 redis,并使用纯 JSON API(无页面/片段缓存)):

  • 您是否缓存单个推文/记录?
  • 或者你是否通过分页缓存记录块(例如20每个的redis列表)?
  • 或者您是否将记录单独缓存在页面中(查看单个推文与 JSON 提要)?
  • 或者你是否为每个不同的场景缓存推文列表:家庭时间线推文、用户推文、用户最喜欢的推文等?还是以上所有?
  • 或者您是否将数据分解为“最易变(最新)”到“最近几天”到“旧”块,其中“旧”数据以更长的到期日期或离散的分页列表或其他方式缓存?而且最新的记录根本没有被缓存。(即,如果数据像推文一样是时间相关的,如果您的旧记录知道它不会有太大变化,您是否会以不同的方式对待它?)

我不明白的是数据更改的比例与是否应该缓存它(并处理缓存到期的复杂性)的比率。似乎 Twitter 可能正在缓存不同的用户推文提要和每个用户的主页推文,但是每次收藏/推文/转发时使缓存无效意味着更新所有这些缓存项(以及可能缓存的记录列表),在某些时候,这似乎意味着使缓存无效会适得其反。

对于像这样变化很大的数据缓存的推荐策略是什么?

4

2 回答 2

4

并不是说 Twitter 是这样做的(尽管我很确定它是相关的),但是:我最近熟悉了CQRS + Event Sourcing。(http://martinfowler.com/bliki/CQRS.html + http://martinfowler.com/eaaDev/EventSourcing.html)。

基本上:读取和写入在应用程序和持久性级别 (CQRS) 上完全分离,并且对系统的每次写入都作为可以订阅的事件进行处理(事件源)。它还有更多功能(例如能够重放整个事件流,这对于以后实现新功能非常有用),但这是相关部分。

在此之后,一般做法是每当负责人(即:它将事件投射到新的读取模型)接收到它订阅的事件类型的新事件时,Read Model都会重新创建(想想内存缓存)Projector.

在这种情况下,一个事件可以是 TweetHandled ,它将由所有订阅者处理,其中 a RecentTweetsPerUserProjectorTimelinePerUserProjector等以更新它们各自的 ReadModel。

结果是最终一致且不需要任何失效的 ReadModel 集合,即:更新的写入和结果事件是更新 ReadModel 开始的触发器。

我同意最终,Charlie Sheen 的读取模型会更新很多(尽管这种更新可能非常有效),因此缓存优势可能非常低。但是,查看普通用户每时间单位的平均帖子,情况就完全不同了。

DDD / CQRS / 事件源领域的一些有影响力的人:Greg Young、Udi Dahan。

这些概念非常“深刻”,所以不要指望在一个小时内完全理解它(至少我没有)。也许这个最近关于相关概念的思维导图也很有用:http: //www.mindmeister.com/de/181195534/cqrs-ddd-links

是的,我对此很感兴趣,如果你还没有注意到的话:)

于 2012-07-24T18:26:03.213 回答
1

我不起眼的 2 美分:Redis 允许您对其数据结构进行操作,这意味着您可以比每次都接触关系数据库更快地进行内存操作。

因此,可以更改“缓存”,使其不会像您期望的那样失效。

在我的项目中,我定期将 500K 记录加载到排序集,然后仅通过对它们进行范围查询来运行统计报告,这使报告执行时间平均低于 2 秒。

于 2012-07-24T16:57:06.560 回答