【问题标题】:How to cache unlimited number of static pages in Rails如何在 Rails 中缓存无限数量的静态页面
【发布时间】:2015-07-31 00:06:10
【问题描述】:

我有一个 Rails 应用程序,它允许用户创建无限数量的静态页面(我将这些页面存储在 postgres 数据库中),因为这些页面是静态的,我想使用页面缓存,但我不确定限制数量是多少/在 Rails 中缓存页面的大小,我可以缓存无限数量的页面吗?

【问题讨论】:

  • 你完全可以,如果你有无限量的资源。
  • 顺便说一句,如果您要缓存所有内容,则最好什么都不缓存。性能将是相同的。您缓存数据是因为它很热,而不是因为它是静态的。
  • @SergioTulentsev 这些页面存储在数据库中,会有什么不同吗?
  • 不,没有任何区别。要缓存所有这些页面,您需要 X gigs 的 RAM。只需向数据库服务器添加该数量的 RAM,这样它就不必将数据分页到磁盘。

标签: ruby-on-rails caching


【解决方案1】:

我们在我们的主要公司博客https://reinteractive.net 上这样做。

您可能想要做的是对要缓存的页面的显示操作进行片段缓存。这样做有一些缺陷,其中最大的缺陷是如果底层页面发生变化,缓存就会过期。

它是这样工作的:

routes.rb 文件中:

AppName::Application.routes.draw do
  get "page/:id" => "pages#show"
end

在控制器中(app/controllers/pages_controller.rb):

class PagesController < ApplicationController::Base
  def show
    @page = Page.find(params[:id])
  end
end

请注意,在控制器中,您在每次请求时都会访问数据库,但这应该是一个非常快的请求,并且具有正确的索引。

然后在视图中(app/views/pages/show.html.erb):

<% cache("pages/show/#{@page.id}-#{@page.updated_at.to_i}") do %>
  <%# Render your complex page here %>
<% end %>

像这样缓存一个片段的好处是,渲染的输出被存储在缓存中,如果这个页面需要一段时间来渲染,你可以节省大量时间,尤其是在渲染需要 100 毫秒或更长时间的情况下页面及其所有部分,您第一次付费,然后在几毫秒内加载。

注意我们正在检查页面的最后更新时间?这样一来,如果您想使此缓存过期(并再次渲染),您只需在要更新的页面对象上调用 page.touch updated_at 时间。

如果您有任何其他也可以更新的对象(例如page.header_image 或其他东西,那么您也可以将这些相关对象上的 updated_at 也放入缓存键中,或者在更新时手动使它们过期页面。

updated_at 添加到缓存键中的另一种方法是在模型中使它们过期,如下所示:

class Page < ActiveRecord::Base
  after_save :expire_cache
  def expire_cache
    Rails.cache.delete("CACHE_KEY")
  end
end

但这有它自己的挑战。

祝你好运!

【讨论】:

  • 他有静态页面。没有复杂的渲染。事实上,如果我理解正确的话,没有任何渲染。只需从数据库中获取并直接流式传输到客户端。
  • @SergioTulentsev 怎么没有渲染?页面由用户创建并存储在数据库中,然后我在视图中呈现该页面,类似于 &lt;%= @page.html_source %&gt; 我的想法是:如果我缓存这些页面,我可能会减少每次用户访问数据库时看到的时间一个页面
  • @medBo:缓存一个每月访问一次的页面是不值得的。您最好将此 RAM 提供给数据库服务器。如果数据在内存中,大多数数据库可以提供与 memcached 相同数量级的吞吐量(当通过主键访问记录时,或者查询是微不足道的)
  • 哦,而且,盲目的性能调整(几乎)总是没有回报。要修复缓慢的部分,您必须识别它们。这意味着分析您的应用程序并实际测量事物。例如,您可能会发现数据库非常快,但您的应用程序非常慢,因为您在某处有 N+1 查询。 (只是一个例子)
  • @SergioTulentsev 我明白了你的意思,但是这些页面不是每个月只访问一次,我的一些用户有数十万的关注者,所以他们给他们的页面带来了巨大的流量!你还认为我不需要做缓存吗?
【解决方案2】:

@MikelLindsaar 的答案很好,但是对于可以更容易处理的事情来说工作量太大了,ActiveRecord 对象有一个名为 cache_key 的方法,如果记录被触摸或更新,它会自动为每条记录生成一个唯一键,生成的key会不一样,这个key是用来生成整个view的缓存key,这个函数有很多参数,比如object id,updated_at(来自cache_key ,以及视图的散列(如果视图文件被更新,缓存会失效,而不仅仅是数据库),所以不用担心任何过时的数据,你需要做的就是:

控制器

class PagesController < ApplicationController::Base
  def show
    @page = Page.find(params[:id])
  end
end

观点

<% cache @page do %>
  <%# Render your page here %>
<% end %>

如果您有多个使用相同页面对象的页面,则可以使用复合缓存键,例如

<% cache(prefix: 'page/show', page: @page) %>

rails 将处理缓存密钥的生成。

更多信息在这里http://guides.rubyonrails.org/caching_with_rails.html#fragment-caching

【讨论】:

  • 我的问题不在于如何缓存页面,而在于是否可以缓存无限数量的页面,因为这些页面是由用户创建的,我不知道他们会创建多少页面...所以我担心在缓存方面存在限制
  • 从这里guides.rubyonrails.org/caching_with_rails.html#cache-stores检查不同的缓存存储,您可以配置缓存以使用文件或内存或redis,最适合您的。
  • @MohammaAbuShady 谢谢你 :) ...我在你的 stackoverflow 地址给你发了一封电子邮件
猜你喜欢
  • 1970-01-01
  • 2010-09-07
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-04-28
  • 1970-01-01
相关资源
最近更新 更多