12

该问题基于 2 篇文章:
-来自 37signals 的 DHH 的Basecamp Next
- Adam Hawkins的 Rails 中的高级缓存

我对使用俄罗斯娃娃缓存的性能影响有点困惑,特别是:

  1. 当使用自动过期键时,似乎每个请求都会导致访问数据库以获取对象时间戳 - 我错过了什么吗?(我知道在最好的情况下,您必须只为层次结构中的顶级键这样做,但仍然......)

  2. 在第 1 篇文章中,他们缓存了一个待办事项列表以及每个待办事项。缓存列表非常有意义,因为它节省了大量工作(所有项目的数据库查询)。但是为什么要缓存单个项目呢?您已经在数据库中获取项目时间戳,那么您到底要保存什么?生成几行html?

  3. 在第 2 篇文章中,Adam 像这样缓存视图的块: cache [post, 'main-content']... cache [post, 'comments'] 添加评论时,它会更改帖子的时间戳,因此会使两个整体无效。然而,main-content并没有改变——你不想重新生成它!!!如何只使评论无效。(这实际上是一个非常常见的用户案例 - 一个具有一些逻辑独立部分的模型:对象本身、不同的关联、其他存储中的数据等)

对我来说,似乎俄罗斯娃娃缓存只有在嵌套对象的层次结构较深时才有意义。(在 basecamp 中,您有项目-> 待办事项列表-> 待办事项-> 项目列表)。但是,如果您的层次结构较浅,最好自己进行失效。

对于任何反馈,我们都表示感谢!
谢谢。

4

2 回答 2

6
  1. 顶层确实需要命中数据库。您可以通过将时间戳存储在单独的缓存条目中来避免这种情况,该条目由模型和 id 键入。文章 1 的一位评论者(Manuel F. Lara)提出了同样的建议:“是否有另一个像 projects/15-time 这样的缓存,你总是拥有项目列表的最后一个时间戳?”

  2. 我认为您对嵌套中的“最低”级别是正确的。您可能需要进行一些测试以查看数据库访问与呈现微小部分的相对性能。

  3. 另一个好点。根据rails docs,如果您将符号传递给:touch它将更新该属性,此外updated_at-也许还有一种方法可以跳过更改Post#updated_at并仅更新comments_updated_at. 然后您可以使用后者进行缓存。但是,如果您试图避免 DB 访问,则必须为此时间戳存储另一个缓存键(如上面的 #1 中所示)。

我想你必须决定这一切是否值得你麻烦。这两篇文章展示了简单、人为的例子来教授这些原则。在具有复杂关联的应用程序中,“分代”缓存方法可能更易于管理。

于 2012-10-19T18:25:41.833 回答
2
  1. 是的。但通常最好的情况和相当好的情况经常出现。
  2. 是的。在我开发的一些应用程序中,渲染视图的时间是执行查询的 10-20 倍。看看你的基准。
  3. 如果渲染帖子的成本很高,您可能不想触摸帖子,而是从[@post.comments.max(:updated_at), @post.comments.size].
于 2012-10-24T11:31:25.667 回答