database - 如果数据不断变化,你缓存什么? (以推特为例)

标签 database caching memcached redis

我花了一些时间研究缓存(主要是 redis 和 memcached),我很难弄清楚当数据不断变化时究竟在哪里使用缓存。

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

假设 Twitter 有这些模型:UserTweetFollowFavorite

有人可能会发布一条推文,一天被转发一次,而另一条推文一天被转发一千次。对于 1000 次转发,由于一天中有大约 24 * 60 == 1440 分钟,这意味着推文几乎每分钟更新一次(假设它也有 440 个收藏)。跟人一样,charlie sheen还被人吸引了1 million Twitter followers in 1 day .在这些情况下缓存似乎不值得,但也许只是因为我还没有达到那个水平。

还可以说,一般的 Twitter 关注者每天至少发推文/关注/收藏一次。这意味着在简单的 intro-rails 模式情况下,用户表每天至少更新一次(tweet_count 等)。这种情况对于缓存用户配置文件很有意义。

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

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

  • 您是否缓存个人推文/记录?
  • 或者您是否通过分页缓存记录 block (例如,每个 20 的 Redis 列表)?
  • 或者您是单独缓存记录还是在页面中缓存记录(查看单个推文与 JSON 提要)?
  • 或者您是否为每个不同的场景缓存推文列表:主页时间线推文、用户推文、用户喜爱的推文等?还是以上所有?
  • 或者您是否将数据分成“最易变(最新)”到“最近几天”再到“旧” block ,其中“旧”数据缓存有较长的到期日期或分成离散的分页列表或其他内容?最新的记录根本就没有被缓存。 (即,如果数据像推文一样依赖于时间,如果您的旧记录知道它不会有太大变化,您是否会区别对待它?)

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

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

最佳答案

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

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

在此之后,一般的做法是,每当负责的Projector(即:它投影一个事件到一个新的读取模型)接收一个它订阅的事件类型的新事件。

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

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

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

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

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

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

关于database - 如果数据不断变化,你缓存什么? (以推特为例),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11625822/

相关文章:

mysql - 从 mysql CLI 创建带有破折号名称的数据库

mysql - mariadb 中的事件时间表

caching - 如何更改 .PyCharm30 缓存/设置文件夹?

http - 在 Windows 7 上以编程方式清除 Internet Explorer 8 中的缓存

php - Memcache store() 和 add() 有什么区别?

php - 我可以像mysql一样在memcached上设置用户名和密码吗?

mysql - 根据 MySQL 中的时间戳列选择距离相等的行

database - 关系数据库的模板匹配

python - 所有迭代器都会缓存吗? csv.Reader 怎么样?

mysql - 使用 Ruby on Rails(一些架构问题)