【问题标题】:Automatic model cache expiry in RailsRails 中的自动模型缓存过期
【发布时间】:2014-09-26 03:39:39
【问题描述】:

我正在阅读一些关于在 Rails 中缓存的指南,但我错过了一些我无法协调的重要内容。

我了解自动过期缓存键的概念,以及它们是如何从模型的 updated_at 属性派生出来的,但我无法弄清楚它是如何在不首先进行数据库查找的情况下知道 updated_at 是什么(即缓存的设计目的究竟是为了避免什么)?

例如:

cache @post

将结果存储在缓存键中,例如:

posts/2-20110501232725

据我了解,Rails 中自动过期的缓存键,如果 @post 被更新(并且 updated_at 属性被改变,那么键将会改变。但我不知道的是,后续如何查找 @post知道如何在不进行数据库查找以获取新的 updated_at 值的情况下获取密钥?Rails 是否必须知道 @post.updated_at 是什么才能访问缓存的版本?

换句话说,如果键包含updated_at时间戳,你怎么能在不知道它是什么的情况下查找缓存呢?

【问题讨论】:

  • 问题似乎不清楚.. 你能改述一下预期的结果是什么吗?如果您尝试过某些东西,最好将其包含在此处
  • 很公平,澄清了我的困惑。
  • 您已更新问题,现在看起来不错...所以回滚否决...

标签: ruby-on-rails caching


【解决方案1】:

在您的示例中,您无法避免访问数据库。然而,这种缓存的目的是避免做额外的工作,每次帖子更改时只需要做一次。从数据库中查找单行应该非常快,然后根据该查找的结果,您可以避免做比单次查找更昂贵的额外工作。

您没有具体说明,但我怀疑您是在视图中执行此操作。在这种情况下,目标是避免在帖子发生之前不会改变的片段构建。与发布相关的各种属性的迭代和渲染这些属性的标记发射可能会很昂贵,具体取决于正在完成的工作,因此鉴于您已经有一个帖子,能够避免这项工作是在这种情况下获得的收益。

【讨论】:

  • 这是一个很好的答案!但是有没有办法使用自动过期的缓存键(可能使用 Rails.cache)或低级缓存来避免数据库命中?
  • 嗯,您可以,但最终您将拥有一个必须维护的不会过期的缓存键。您可以将该帖子的元数据保存在缓存条目中,读取它,然后将其用作缓存键,但此时您基本上只是将缓存存储视为第二个数据库,以从中查找缓存键信息- 你总是必须从某处获取这些信息。如果缓存非常快而数据库访问非常慢,这可能是值得的,但否则复杂性成本可能不值得任何性能提升。
  • 是的,我明白这一点,只是我正在处理一个流量非常大的网站,我正在尝试找到一种方法来减少数据库 IOPS 的数量以提供帮助具有站点可扩展性。我并不是要好战,但如果我理解正确,简短的回答是数据库和网络服务器堆栈之间的任何缓存都需要手动完成。这是正确的吗?
  • 好吧,你可以使用任何你想要的自动过期缓存键,但你必须从某个地方获取它——从这个意义上说,它是手动的(你可能不想缓存例如,DB 会在请求之间导致内存中),但是如果您选择的缓存键会自然而然地自行过期,Rails 确实可以轻松做到这一点。不过,如果规模是一个大问题,您可能会研究像 Varnish 这样的完整请求缓存技术。
【解决方案2】:

据我了解您的问题。您正试图弄清楚缓存如何工作的黑魔法。祝你好运。

但我认为根本问题是更新是如何发生的?

缓存元素应该有一个基于元素某些部分的逻辑键,例如复合键,基于项目 ID 的一些键名。您构建此密钥以在需要时调用缓存片段。关键总是相同的,否则你不能确定你得到了你想要的。

缓存的一个基本假设是缓存值是暂时的,即如果它消失或过时,这没什么大不了的。如果这很重要,那么缓存不是解决问题的方法。缓存旨在减轻高负载,即大量流量在您的数据库中遇到相同的事情。类似于一个博客,其中 1,000,000 人可能正在阅读特定的博客文章。它并不意味着加速您的数据库。这是通过 SQL 优化、分片等来完成的。

如果您使用 Dalli 作为缓存存储,则可以设置到期时间。

Rails AFAIK 中的缓存循环基本上是这样工作的:

所以回答你的问题:

密钥在您更新时更新。与帖子更新相关的操作。您可以设置到期时间,这基本上通过新的查找/缓存写入强制缓存更新来实现所需的结果。就缓存而言,它总是读取与键对应的缓存元素。如果它被更新,那么它将读取更新的元素,但它不是缓存检查数据库的责任。

您可能正在寻找类似prepared statement 的内容。 Tenderlove on Prepared Statements 或更快的数据存储,如不太安全的 Postgres(即在没有 ACID 的情况下调整到 NoSQL)或 NoSQL 类型的数据库。

您的数据库中还有索引吗?如果没有适当的索引,数据库请求会很慢。您可能只需要“调整”您的数据库。

还有一个很棒的 gem,叫做 cells,它可以让你对视图做更多的事情,包括更快的返回和渲染部分,至少在我的经验中是这样。它还具有一些缓存功能。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2012-02-09
    • 1970-01-01
    • 2014-05-07
    • 2021-05-29
    • 1970-01-01
    • 1970-01-01
    • 2013-02-10
    相关资源
    最近更新 更多