2

我正在向既有登录用户又有匿名用户的 Rails 3 站点添加片段缓存,并且需要根据整个站点显示的内容何时更新来控制页面的某些部分何时过期。在此过程中,我发现 memcached 不支持 expire_fragment 的正则表达式,所以现在我正在寻找解决方法。

对于匿名用户来说,这不是一个大问题。我创建缓存键,例如“frontpage-new-shows”或“schedule-weekly-forecast-10/24/10”,并在 Show 模型中出现新条目或下周播出的节目时使它们过期通过清扫器进行修改。这工作得很好。

我的问题是登录的用户。他们每个人都有自己定制的时间表,所以我的密钥看起来像“schedule-user-jschuur-10/10/24”,而 jschuur 是帐户的用户名。我知道,使用基于日期的约定,它们自然会过期,但我也想在当天(或一周)的日程安排中发生与显示相关的更改时,显式地使缓存日程安排的所有片段过期。

事实证明,memcached 无法执行我需要的那种通配符过期(schedule-user-.*-10/10/24)。这意味着我需要某种解决方案来存储在 memcached 中的中央查找键中发出的所有键,或者让 Rails/Ruby 根据我为我发送到 memcached 的键在内部以某种方式执行此操作。

我假设前者是更好的解决方案。我的问题是,我如何以最有效的方式做到这一点,所以我不会一直吹,不再打数据库。我可以在 memcached 中存储一个数组或散列,检索整个内容,循环查找匹配项,删除它们并将散列存储回来。这听起来对几百甚至一千名用户来说可能很有效,但这真的是最好的方法吗?

有人已经解决了这个问题并发布了解决方案吗?

需要考虑的一件事是,我目前几乎所有的缓存都是通过视图中的语句完成的,面向 ActiveRelations 准备好的尚未触发的查询,例如:

<% if current_user %>
  <% if current_user.saved_shows_count %>
    <% cache "schedule-user-#{current_user.username}-#{(Time.now + 3.hours).to_date.end_of_week.strftime('%D')}" do %>
      <% if @shows.any? %>
        <%= render :partial => "schedule/schedule", :locals => { :shows => @shows } %>
      <% end %>
    <% end %>
...

该站点托管在 Heroku 上,我使用 dalli gem 作为客户端。

4

1 回答 1

5

编辑:使用 dalli gem 编写的内容存在一些问题,对我来说,读取会引发“编组数据太短”或“内存缓存中的编组数据无效”。不确定它是否也适合你。

虽然有点 hackish,但您可以使用命名空间,然后增加命名空间,从而使使用它创建的所有密钥无效。为此,首先在初始化程序(或任何地方)中使用Rails.cache.write("frontpage-new-shows-namespace", "1", {:raw => true}). 当你设置每个缓存时,Rails.cache.read("frontpage-new-shows-namespace")在你想要的任何地方添加到哈希键中(在哪里并不重要)。使命名空间中创建的所有缓存键过期就像Rails.cache.increment("frontpage-new-shows-namespace", 1). 您可能能够添加Rails.cache.read("frontpage-new-shows-namespace")为全局变量,从而消除创建缓存键的 memcache 搜索,然后在您执行缓存命名空间增量时更新此变量。

祝你好运,我希望这会有所帮助。

于 2010-10-25T17:16:18.367 回答