0

我有一个来自当前用户正在关注的用户事件的动态提要,部分内容都是 memcached,但我也想为提要本身做这件事。我担心的是,如果我对它进行内存缓存,它将根据对缓存的第一次写入为每个用户显示相同的内容,而不是为每个唯一用户动态显示。

我将如何对提要和@following 进行内存缓存?如果当前用户关注另一个用户,我如何更新它?我假设我不能只用 <% cache "feed" do %> 包装它

注意:使用 Memcached 和 Dalli

<% @following = current_user.following.collect {|f| f["id"]} %>
<div class='content'>
<% unless Rsvp.where(:voter_id => @following, :status => 'going').where("start_time > ? AND start_time < ?", Time.now, Time.now.strftime('%Y-%m-%d 23:59:59.000000')).order("count_all desc").count(:group => :event_id).collect { |f| f[0] }.count == 0 %>
          <div class='date_bar_container'><div class='date_bar'>Today</div></div>
          <div class='content_wrapper'>
    <%= render :partial => 'events/event', :collection => Event.where(:id =>  Rsvp.where(:event_id => Rsvp.where(:voter_id => @following, :status => 'going').where("start_time > ? AND start_time < ?", Time.now.strftime('%Y-%m-%d 00:00:00.000000'), Time.now.strftime('%Y-%m-%d 23:59:59.000000')).order("count_all desc").count(:group => :event_id).collect { |f| f[0] }).select("DISTINCT event_id").collect(&:event_id)).order('start_time asc')%>
          </div>
<% end %>

<% unless Rsvp.where(:voter_id => @following, :status => 'going').where("start_time > ? AND start_time < ?", (Time.now + 1.day).strftime('%Y-%m-%d 00:00:00.000000'), (Time.now + 1.day).strftime('%Y-%m-%d 23:59:59.000000')).order("count_all desc").count(:group => :event_id).collect { |f| f[0] }.count == 0%>
          <div class='date_bar_container'><div class='date_bar'>Tomorrow</div></div>
          <div class='content_wrapper'>
    <%= render :partial => 'events/event', :collection => Event.where(:id =>  Rsvp.where(:event_id => Rsvp.where(:voter_id => @following, :status => 'going').where("start_time > ? AND start_time < ?", (Time.now + 1.day).strftime('%Y-%m-%d 00:00:00.000000'), (Time.now + 1.day).strftime('%Y-%m-%d 23:59:59.000000')).order("count_all desc").count(:group => :event_id).collect { |f| f[0] }).select("DISTINCT event_id").collect(&:event_id)).order('start_time asc')%>
    </div>
    <% end %>

<% (2..15).each do |f| %>
    <% unless Rsvp.where(:voter_id => @following, :status => 'going').where("start_time > ? AND start_time < ?", (Time.now + f.day).strftime('%Y-%m-%d 00:00:00.000000'), (Time.now + f.day).strftime('%Y-%m-%d 23:59:59.000000')).order("count_all desc").count(:group => :event_id).collect { |f| f[0] }.count == 0 %>
              <div class='date_bar_container'><div class='date_bar'><%= dayofweek((Time.now + f.day).wday) %>, <%= month((Time.now + f.day).month) %> <%= (Time.now + f.day).day %>, 2012</div></div>
              <div class='content_wrapper'>
        <%= render :partial => 'events/event', :collection => Event.where(:id =>  Rsvp.where(:event_id => Rsvp.where(:voter_id => @following, :status => 'going').where("start_time > ? AND start_time < ?", (Time.now + f.day).strftime('%Y-%m-%d 00:00:00.000000'), (Time.now + f.day).strftime('%Y-%m-%d 23:59:59.000000')).order("count_all desc").count(:group => :event_id).collect { |f| f[0] }).select("DISTINCT event_id").collect(&:event_id)).order('start_time asc')%>
         </div>
        <% end %>
<% end %>
</div>
4

1 回答 1

0

不相关,但您的视图中的模型代码/ sql 太多了。将它们打包在类方法或范围中。

关于缓存,如果您不希望每个用户看到相同的内容,那么您需要为每个用户设置不同的缓存键。这样做的一种方法是传递action_suffix选项,该选项会添加到用于生成缓存键的数据中(默认情况下它只是控制器和操作)。如果您将当前用户 ID 作为其中的一部分,那么缓存将基于每个用户完成。您还可以将带有任意缓存键的字符串传递给用户,而不是从控制器、操作和操作后缀构建它。

据说缓存到期是计算机科学中的两件困难的事情之一。至少有3个选项:

  • 当您缓存某些内容时,请将 expires_in 设置为适当的时间跨度。当基础数据发生变化时:您接受用户看到的内容在您设置的时间跨度内可能已经过时。将其设置得高,他们会在很长一段时间内看到陈旧的数据,设置得太低,您将丢弃本可以保留的缓存数据。

例如:

 <% cache({:action_suffix => 'blah'}, :expires_in => 20.minutes  do %>
  ..
 <% end %>
  • 显式过期数据以响应模型更改,例如通过清扫器。记住所有可能发生这种情况的地方并记住在添加新东西时增加清扫器可能会很棘手

  • 使用分代缓存键:构造您的缓存键,以便当基础数据更改时,缓存键也会更改。一个非常简单的示例是,如果您正在缓存有关用户的信息页面。您可以将缓存键设置为user_#{user.id}_#{user.updated_at.to_i}(或等效地,user.cache_key)。当用户更改时,无论如何,您使用的缓存键也会更改(因为updated_at将更改),因此您不会使用旧的缓存数据

于 2012-10-26T00:41:34.137 回答