如果数据不断变化,你会缓存什么?(以Twitter为例)

Lan*_*ard 18 database memcached caching redis

我花了一些时间研究缓存(主要是redis和memcached),并且在数据不断变化时很难确定在哪里使用缓存.

以Twitter为例(只需阅读使Twitter快10000%).当大部分数据库记录不断变化时,您(或他们)如何缓存数据?

说Twitter也有这些模型:User,Tweet,Follow,Favorite.

有人可能会发布一条推文,它会在一天内被转发一次,而另一条推文会在一天内转发一千次.对于那个1000x转推,因为24 * 60 == 1440一天大约几分钟,这意味着Tweet几乎每分钟更新一次(说它也有440个收藏).与追随某人相同,查理光泽甚至在1天内吸引了100万Twitter追随者.在这些情况下缓存似乎并不值得,但也许只是因为我尚未达到这个水平.

另请注意,普通的Twitter粉丝每天至少发一次推文/关注/收藏.这意味着在天真的intro-rails架构案例中,users表每天至少更新一次(tweet_count等等).这种情况对于缓存用户配置文件很有意义.

但对于上面的1000x Tweets和1M粉丝示例,在缓存数据方面有哪些推荐做法?

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

  • 你是否缓存个别推文/记录?
  • 或者你通过分页缓存大块的记录(例如20每个的redis列表)?
  • 或者您是单独还是在页面中缓存记录(查看单个推文与JSON提要)?
  • 或者你是否为每个不同的场景缓存推文列表:家庭时间线推文,用户推文,用户喜欢的推文等?或者以上所有?
  • 或者您是否将数据分为"最不稳定(最新)"到"最近几天"到"旧"块,其中"旧"数据缓存的有效日期较长或者是离散的分页列表或其他内容?并且最新的记录根本没有缓存.(即如果数据与推文有时间关系,那么如果您的旧记录知道它不会发生太大变化,您会不同地对待它?)

我不明白的是数据变化的比例与缓存它的比例(以及处理缓存到期的复杂性).看起来Twitter可以缓存不同的用户推文提要,以及每个用户的家庭推文,但是每次收藏/推文/转推意味着更新所有这些缓存项(以及可能缓存的记录列表)时,缓存都会使缓存无效,在某些时候,它似乎意味着无效缓存是适得其反的.

缓存数据的推荐策略是什么?

Gee*_*Jan 5

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

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

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

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

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

我同意,最终,查理·辛 (Charlie Sheen) 的读取模型会更新很多(尽管这种更新可能非常有效),因此缓存优势可能相当低。然而,如果看看普通用户每个时间单位的平均发帖量,情况就完全不同了。

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

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

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


Nil*_*oct 1

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

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

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