使用分页(kaminari)时如何使用dalli实现片段缓存? [英] How can I implement fragment cache with dalli when using pagination (kaminari)?

查看:34
本文介绍了使用分页(kaminari)时如何使用dalli实现片段缓存?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我知道 dalli(缓存)是非常强大的插件,可以增强静态页面的性能.
但是经常更新的带有分页的动态页面呢?
设置 dalli 的正确方法是什么?

我遇到的一个问题,例如:dalli 在使用分页时将不同的 params[:page] 识别为同一页面:(

当两者都使用 dalli 时,你们会如何设计系统

  • 经常更新的页面
  • 不会经常更新的页面

例如.我有 4 个模型,例如 UserCommunityTopicComment(定义了社区和主题的多态.他们可以在#show pages中创建或显示)

就像

  • 社区 > (has_many) > 主题 > (has_many) > 评论
  • 社区 > (has_many) > 评论
  • 它们都属于用户(创建者)

我目前的代码就是这样(这有点长.抱歉)
我在使用缓存时遇到分页问题...

-------------------------------------设置-----------------------------------------

config/environments/development.rb

config.think_all_requests_local = trueconfig.action_controller.perform_caching = trueconfig.cache_store = :dalli_store

routes.rb

资源:社区做资源:主题做资源:评论做结尾结尾

--------------------------------------社区-----------------------------------------

controllers/communities_controller.rb#index&show

caches_page :showcaches_action :edit, :new定义索引....if params[:sort] == 'new'@communities = Community.scoped.page(params[:page]).order("created_at DESC")elsif params[:sort] = '流行'@communities = Community.scoped.page(params[:page]).order("follow_count DESC")elsif params[:sort] = '声誉'@communities = Community.scoped.page(params[:page]).order("reputation_count DESC")别的@communities = Community.scoped.page(params[:page]).order("created_at DESC")结尾....结尾高清秀@community = Community.find(params[:community_id])@comments @community.comments.page(params[:page]@topics = @community.topics.limit(10)结尾

views/communities/index.html.erb注意:但是,即使我移动到下一个 params[:page]:( 似乎缓存将不同的页面识别为相同的内容...

#here, url 可能类似于 example.com/communities?utf8=✓&location=14&genre=3&search=strawberry但这将创建巨大的缓存宠物:(所以我想让它只在 params[:sort] 不为空时才起作用.因为,当 params[:sort] 不为空时,没有其他参数.它可能是这样的,example.com/communities?sort=new,example.com/communities?sort=popular,example.com/communities?sort=reputation...<% if params[:sort] %><% @key = "community_index_" + params[:sort] + params[:page] %><% cache(:controller => "communities", :action => "index", :action_suffix => @key) do %><%= page_entries_info(@communities, :entry_name => 'community').html_safe %><%= 分页 @communities, :window =>4%><% @communities.each 做 |community|%><%= 渲染社区/社区",:community =>社区%><%结束%><%结束%><%结束%>...

views/communities/show.html.erb

<代码>...<% @key = params[:community_name] + "_community_show_information" %><% cache(:controller => "communities", :action => "show", :action_suffix => @key) do %><h2>信息</h2><div class="社区信息"><%=呈现'社区/信息'%>

<%结束%><% @key = params[:community_name] + "_community_show_wall_" + params[:page] + %><% cache(:controller => "communities", :action => "show", :action_suffix => @key) do %><%= 分页 @comments, :window =>4%><h2>主题</h2><div class="WallInformation"><% @comments.eager.recent.each 做 |comment|%><%= 渲染社区/评论",:comment =>评论 %><%结束%>

<%结束%><% @key = params[:community_name] + "_community_show_topics" %><% cache(:controller => "communities", :action => "show", :action_suffix => @key) do %><h2>主题</h2><div class="TopicInformation"><% @topics.eager.recent.each 做 |topic|%><%= 渲染社区/主题",:topic =>主题%><%结束%>

<%结束%>...

models/community_sweeper.rb

class CommunitySweeper  'index', :only_path => true) + '?????(所有与社区相关的缓存#index)')expire_fragment(url_for(:action => 'show', :only_path => true) + '?????(与特定社区相关的缓存#show)')结尾结尾结尾

-------------------------------------主题-----------------------------------------

controllers/topics_controller.rb#index&show

caches_page :showcaches_action :edit, :new定义索引....@community = Community.find(params[:community_id])@topics = @community.topics.page(params[:page]....结尾高清秀@topic = Topic.find(params[:id])@comments = @topic.comments.page(params[:page]结尾

views/topics/index.html.erb

<代码>...<% @key = params[:community_id] + "_topic_index_" + params[:page] %><% cache(:controller => "topics", :action => "index", :action_suffix => @key) do %><%= page_entries_info(@communities, :entry_name => 'community').html_safe %><%= 分页 @communities, :window =>4%><% @communities.each 做 |community|%><%= 渲染社区/社区",:community =>社区%><%结束%><%结束%><%结束%>...

views/topics/show.html.erb

<代码>...<% @key = params[:community_name] + "_topic_show_" + params[:id] + "_comments" + params[:page] %><% cache(:controller => "topics", :action => "show", :action_suffix => @key) do %><%= 分页 @comments, :window =>4%><%= page_entries_info(@comments, :entry_name => 'comment').html_safe %><h2>评论</h2><div class="CommentInformation"><% @comments.each 做 |comment|%><%= 渲染 'topics/comment', :comment =>评论 %><%结束%>

<%结束%>...

models/topic_sweeper.rb

class TopicSweeper  'index', :only_path => true) + '?????(所有与主题相关的缓存#index)')expire_fragment(url_for(:action => 'show', :only_path => true) + '?????(与特定主题相关的缓存#show)')结尾结尾

-------------------------------------评论-----------------------------------------

models/comment_sweeper.rb

class CommentSweeper <ActionController::Caching::Sweeper观察评论def after_save(记录)expire_fragment(url_for(:action => 'index', :only_path => true) + '?????(所有与主题相关的缓存#index)')expire_fragment(url_for(:action => 'show', :only_path => true) + '?????(与特定主题相关的缓存#show)')结尾结尾

解决方案

我继续我对

的回答

我应该如何为包含大量内容更新的动态页面设置 dalli?

请注意,我不是专家,但我确实尝试了您的方法并放弃了它,因为随着我的应用程序的增长它变得越来越复杂,我选择了上一个问题中提到的基于缓存键片段的方法.有几点需要牢记.

  1. 缓存清除程序方法要求您在更改应用程序时确保清除程序是最新的,这意味着额外的维护和测试工作.

  2. 在动态应用程序中,您可能无法轻松缓存整个页面,尤其是当视图显示来自多个模型的信息时.

  3. 除非 page 参数成为缓存键的一部分,否则您将无法处理分页问题.

  4. 当您的缓存已满时,memcached 会在放入新缓存片段时删除最少使用/最旧的缓存项.

  5. 因此,当您的模型发生变化时,您只需推送新的缓存片段并让 memcached 清除旧的过时缓存项目就没有问题.

因此,视图中的片段缓存可能是最简单的解决方案,因为它将处理分页,而您不必处理手动缓存失效

所以看看你的一个观点,我可能会做的是

<% if params[:sort] %><%= page_entries_info(@communities, :entry_name => 'community').html_safe %><%= 分页 @communities, :window =>4%><% @communities.each 做 |community|%><% cache(community, :suffix => "community_index") 做<%= 渲染社区/社区",:community =>社区%><%结束%><%结束%><%结束%>

我所做的是缓存每个社区记录的渲染,分页变得无关紧要

I know dalli (caching) is pretty powerful plugin to enhance performance for static pages.
But what about dynamic pages with pagination, which are updated quite often?
What is the correct way to set up dalli?

One problem I've encountered for example: dalli recognizes different params[:page] as the same page when using pagination:(

How would you guys design the system when using dalli for both

For example. I have 4 models such as User, Community, Topic, and Comment(defined Polymorphic to both Community, and Topic. They can be created or shown in #show pages)

It's like

My current codes are just like this(This is quite bit long. Sorry about that)
I'm facing the pagination problem when using caching...

-------------------------------------Settings----------------------------------------

config/environments/development.rb

config.consider_all_requests_local       = true
config.action_controller.perform_caching = true
config.cache_store = :dalli_store

routes.rb

resources :communities do
    resources :topics do
        resources :comments do
    end
end

-------------------------------------Community----------------------------------------

controllers/communities_controller.rb#index&show

caches_page :show
caches_action :edit, :new

def index
    ....
    if params[:sort] == 'new'
        @communities = Community.scoped.page(params[:page]).order("created_at DESC")
    elsif params[:sort] = 'popular'
        @communities = Community.scoped.page(params[:page]).order("follow_count DESC")
    elsif params[:sort] = 'reputation'
        @communities = Community.scoped.page(params[:page]).order("reputation_count DESC")
    else
        @communities = Community.scoped.page(params[:page]).order("created_at DESC")
    end
    ....
end

def show
    @community = Community.find(params[:community_id])
    @comments @community.comments.page(params[:page]
    @topics = @community.topics.limit(10)
end

views/communities/index.html.erb note: However, the content will be the same even if I move to next params[:page]:( It seems caching recognize different page as the same contents...

#here, the url will could be something like this example.com/communities?utf8=✓&location=14&genre=3&search=strawberry
 But this is going to create gigantic petterns of the caches:(  
 So I want to make it work only when params[:sort] was not empty. Because, no other parameters come with when params[:sort] is not empty. 
 It could be like, example.com/communities?sort=new, example.com/communities?sort=popular, example.com/communities?sort=reputation


...
<% if params[:sort] %>
    <% @key = "community_index_" + params[:sort] + params[:page] %>

    <% cache(:controller => "communities", :action => "index", :action_suffix => @key) do %>
        <%= page_entries_info(@communities, :entry_name => 'community').html_safe %>
        <%= paginate @communities, :window => 4 %>

        <% @communities.each do |community| %>  
            <%= render 'communities/community', :community => community %>
        <% end %>
    <% end %>
<% end %>
...

views/communities/show.html.erb

...
<% @key = params[:community_name] + "_community_show_information" %>
<% cache(:controller => "communities", :action => "show", :action_suffix => @key) do %>
    <h2>Information</h2>
    <div class="CommunityInformation">
        <%= render 'communities/information'%>
    </div>
<% end %>


<% @key = params[:community_name] + "_community_show_wall_" + params[:page] + %>
<% cache(:controller => "communities", :action => "show", :action_suffix => @key) do %>
<%= paginate @comments, :window => 4 %>
    <h2>Topic</h2>
    <div class="WallInformation">
        <%  @comments.eager.recent.each do |comment| %>
            <%= render 'communities/comment', :comment => comment %>
        <% end %>
    </div>
<% end %>

<% @key = params[:community_name] + "_community_show_topics" %>
<% cache(:controller => "communities", :action => "show", :action_suffix => @key) do %>
    <h2>Topic</h2>
    <div class="TopicInformation">
        <%  @topics.eager.recent.each do |topic| %>
            <%= render 'communities/topic', :topic => topic %>
        <% end %>
    </div>
<% end %>
...

models/community_sweeper.rb

class CommunitySweeper < ActionController::Caching::Sweeper
  observe Community


  def after_save(record)
    expire_fragment(url_for(:action => 'index', :only_path => true) + '?????(all the caches related to the community#index)')
    expire_fragment(url_for(:action => 'show', :only_path => true) + '?????(the cache related to the particular community#show)')
  end
end

end

-------------------------------------Topic----------------------------------------

controllers/topics_controller.rb#index&show

caches_page :show
caches_action :edit, :new

def index
    ....
    @community = Community.find(params[:community_id])
    @topics = @community.topics.page(params[:page]
    ....
end

def show
    @topic = Topic.find(params[:id])
    @comments = @topic.comments.page(params[:page]
end

views/topics/index.html.erb

...
<% @key = params[:community_id] + "_topic_index_"  + params[:page] %>
    <% cache(:controller => "topics", :action => "index", :action_suffix => @key) do %>
        <%= page_entries_info(@communities, :entry_name => 'community').html_safe %>
        <%= paginate @communities, :window => 4 %>

        <% @communities.each do |community| %>  
            <%= render 'communities/community', :community => community %>
        <% end %>
    <% end %>
<% end %>
...

views/topics/show.html.erb

...    
<% @key = params[:community_name] + "_topic_show_" + params[:id] + "_comments" + params[:page] %>
    <% cache(:controller => "topics", :action => "show", :action_suffix => @key) do %>
         <%= paginate @comments, :window => 4 %>
         <%= page_entries_info(@comments, :entry_name => 'comment').html_safe %>

         <h2>Comment</h2>
         <div class="CommentInformation">
         <% @comments.each do |comment| %>
             <%= render 'topics/comment', :comment => comment %>
         <% end %>
    </div>
<% end %>
...

models/topic_sweeper.rb

class TopicSweeper < ActionController::Caching::Sweeper
  observe Topic


  def after_save(record)
    expire_fragment(url_for(:action => 'index', :only_path => true) + '?????(all the caches related to the topic#index)')
    expire_fragment(url_for(:action => 'show', :only_path => true) + '?????(the cache related to the particular topic#show)')
  end
end

-------------------------------------Comment----------------------------------------

models/comment_sweeper.rb

class CommentSweeper < ActionController::Caching::Sweeper
  observe Comment


  def after_save(record)
    expire_fragment(url_for(:action => 'index', :only_path => true) + '?????(all the caches related to the topic#index)')
    expire_fragment(url_for(:action => 'show', :only_path => true) + '?????(the cache related to the particular topic#show)')
  end
end

解决方案

I am following on on from my answer to

How should I set up dalli for a dynamic page with lots of content updates?

Please note that I am not an expert but I did try your approach and abandoned it as it just kept getting more and more complex as my application grew and I went for the cache key fragment based approach mentioned in the last question. There are a few things to bear in mind.

  1. The cache sweeper approach requires you to make sure that the sweeper is up to date as you make changes to your application which means extra maintenance and testing work.

  2. In a dynamic application you probably wont be able to easily cache whole pages especially if the views show information from many models.

  3. You wont be able to deal with the paging issue unless the page parameter becomes part of your cache keys.

  4. When your cache gets full, memcached will simply remove the least used / oldest cache items when putting in a new cache fragment.

  5. So there is no issue with you just pushing in a new cache fragments when your models change and letting memcached clear out the old out of date cache items.

Therefore fragment caching in your views will probably be the easiest solution as it will deal with paging and you wont have to deal with manual cache invalidation

So looking at one of your views, what I might do is

<% if params[:sort] %>

        <%= page_entries_info(@communities, :entry_name => 'community').html_safe %>
        <%= paginate @communities, :window => 4 %>

        <% @communities.each do |community| %>  
            <% cache(community, :suffix => "community_index") do 
                <%= render 'communities/community', :community => community %>
            <% end %>
        <% end %>
<% end %>

What I have done is cache the rendering of each community record and paging becomes irrelavent

这篇关于使用分页(kaminari)时如何使用dalli实现片段缓存?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
其他开发最新文章
热门教程
热门工具
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆