为什么需要设置缓存的到期时间?

时间:2013-06-10 21:06:10

标签: ruby-on-rails

我没有在Rails缓存指南http://guides.rubyonrails.org/caching_with_rails.html中解释这个问题,所以我想知道我是否可以问一下缓存在这个例子中是如何工作的。在我的用户个人资料页面上,我缓存了用户说的语言,并设置了15分钟的到期时间。当我这样做时,我假设如果用户在15分钟到期之前更新了他的语言,那么更新的语言就不会显示,因为缓存没有过期。但是,当我在我的应用程序上测试它时,更新的语言会立即显示,所以我认为更新会破坏缓存。如果是这种情况,那么为什么我不能将到期日设置为1小时或无限?

  @languages = Rails.cache.fetch("lang", :expires_in => 15.minutes) do
    Language.where({:user_id => @user.id})
  end

注意,如果重要的话,我正在使用Rails 4和memcached。

更新,如果到期时间只是因为大小限制而清除缓存,我应该为多长时间设置?

我的个人资料页面上有很多信息(大约有15个类似于下面的查询),如果用户不断刷新页面,我宁愿缓存这些信息,因此我只是要这样做

 @endorsements = Rails.cache.fetch("endorsements", :expires_in => 15.minutes) do
    Endorsement.where({:subject_id => @user.id})
  end

  @languages = Rails.cache.fetch("lang", :expires_in => 15.minutes) do
    Language.where({:user_id => @user.id})
  end

2 个答案:

答案 0 :(得分:2)

你实际上并没有缓存任何东西:你只是缓存ActiveRecord::Relation个对象(这只是查询的红宝石描述),而不是查询结果本身。

每次代码运行时,此查询都会以未执行状态拉出,然后再次运行。要实现您想要执行的操作,您需要强制执行查询,例如

 @endorsements = Rails.cache.fetch("endorsements", :expires_in => 15.minutes) do
    Endorsement.where({:subject_id => @user.id}).all
 end

缓存过期可能很棘手 - 有时候缓存项会自动过期而不是确保每种更改数据的方式都会清除缓存。在某些情况下,您甚至可能不知道数据何时发生更改,例如,如果您正在缓存外部API调用的结果。

答案 1 :(得分:1)

以下是您在Rails4中需要做的事情,以便按照您的预期使缓存工作(在开发中):

  1. 将'dalli'添加到您的Gemfile
  2. config.cache_store = :mem_cache_store添加到您的config / environments / development.rb
  3. config.action_controller.perform_caching = true添加到您的config / environments / development.rb
  4. (我知道你已经完成了#3)

    完成此操作后,您将不再在日志中看到“SELECT *”,当您更新模型时,它不会自动更新您的缓存。

    更新:

    就像@FrederickCheung所说,你需要缓存对象,而不是关系(查询)。最好的办法就是给他们打电话“to_a”。