如何在Ubuntu12.04LTS上将Memcached与RubyonRails一起使用

来自菜鸟教程
跳转至:导航、​搜索


状态: 已弃用

本文介绍了不再受支持的 Ubuntu 版本。 如果您当前正在运行运行 Ubuntu 12.04 的服务器,我们强烈建议您升级或迁移到受支持的 Ubuntu 版本:

原因: Ubuntu 12.04 已于 2017 年 4 月 28 日终止生命周期 (EOL) and no longer receives security patches or updates. This guide is no longer maintained.

请参阅:
本指南可能仍可用作参考,但可能不适用于其他 Ubuntu 版本。 如果可用,我们强烈建议使用为您正在使用的 Ubuntu 版本编写的指南。 您可以使用页面顶部的搜索功能来查找更新的版本。


介绍

Memcached 是一个非常快速的内存对象缓存系统,它可以使 Rails 运行得更快,只需很少的更改。

先决条件:

本教程假设您已经安装了 Ruby on Rails 和 Memcached。 如果没有,教程链接如下:

它还假设您的 Rails 应用程序已启动并正在运行,并准备好使用 Memcached 进行优化。

安装达利宝石

我们要做的第一件事是安装 Mike Perham's Dalli Gem

gem install dalli

如果您使用 Bundler,则将 gem 'dalli' 添加到您的 Gemfile 并运行 bundle install

这将是我们与 Memcached 交互的超快速且功能丰富的方式。

配置 Rails

将 Rails 配置为使用 memcached 的第一步是编辑您的 config/environments/production.rb 并添加此行以告诉 Rails 使用 Dalli:

config.cache_store = :dalli_store

接下来,我们将告诉 ActionController 执行缓存。 将此行添加到同一文件中:

config.action_controller.perform_caching = true

现在,像往常一样重新启动 Rails 应用程序。

更改您的 Rails 应用程序

为了利用我们刚刚所做的更改,需要更新 Rails 应用程序。 有两种主要方法可以利用 memcached 为您提供的加速。

添加缓存控制标头

利用 memcached 的最简单方法是将 Cache-Control 标头添加到您的操作之一。 这将使 Rack::Cache 为您将该操作的结果存储在 memcached 中。 如果在 app/controllers/slow_controller.rb 中有以下动作:

def slow_action
  sleep 15
  # todo - print something here
end

我们可以添加以下行来告诉 Rack::Cache 将结果存储五分钟:

def slow_action
  expires_in 5.minutes
  sleep 15
  # todo - print something here
end

现在,当您第二次执行此操作时,您会发现它明显更快。 Rails 只需每五分钟执行一次即可更新 Rack::Cache。

请注意,这会将 Cache-Control 标头设置为公共。 如果您有某些只有一位用户可以看到的操作,请使用 expires_in 5.minutes, :public => false。 您还必须确定缓存响应的适当时间,这因应用程序而异。

如果您想了解有关 HTTP 缓存的更多信息,请查看 Mark Nottingham ' 的 Web 作者和网站管理员缓存教程

在 Memcached 中存储对象

如果您有一个非常昂贵的操作或每次都必须创建的对象,您可以在 memcached 中存储和检索它。 假设您的操作如下所示:

def slow_action
  slow_object = create_slow_object
end

我们可以通过更改如下操作将结果存储在 memcached 中:

def slow_action
  slow_object = Rails.cache.fetch(:slow_object) do 
      create_slow_object
  end
end

Rails 将向 memcached 请求带有 'slow_object' 键的对象; 如果它没有找到该对象,它将执行给定的块并将对象写回其中。

片段缓存

片段缓存是 Rails 的一项功能,可让您选择应用程序的哪些部分最动态且需要优化。 您可以轻松地将视图周围的任何部分缓存在 cache 块中:

<% # app/views/managers/index.html.erb  %>
<% cache manager do %>
  Manager's Direct Reports:
  <%= render manager.employees %>
<% end %> 

<% # app/views/employees/_employee.html.erb %>
<% cache employee do %>
    Employee Name: <%= employee.name %>
    <%= render employee.incomplete_tasks %>
<% end %>

<% # app/views/tasks/_incomplete_tasks.html.erb %>
<% cache task do %>
    Task: <%= task.title %>
    Due Date: <%= task.due_date %>
<% end %>

上述技术被称为俄罗斯娃娃缓存,暗指传统的俄罗斯套娃。 然后 Rails 会将这些片段缓存到 memcached 中,并且由于我们将模型添加到 cache 语句中,因此该缓存对象 ' 的键将在对象更改时更改。 但是,这产生的问题是任务更新时:

@todo.completed!
@todo.save!

由于我们将缓存对象嵌套在缓存对象中,Rails 不会知道依赖此模型的缓存片段是否过期。 这就是 ActiveRecord touch 关键字派上用场的地方:

class Employee < ActiveRecord::Base
  belongs_to :manager, touch: true
end

class Todo < ActiveRecord::Base
  belongs_to :employee, touch: true
end

现在,当 Todo 模型更新时,它将过期其缓存片段并通知 Employee 模型它也应该更新其片段。 然后 Employee 片段将通知 Manager 模型,在此之后,缓存过期过程完成。

俄罗斯娃娃缓存为我们带来了另一个问题。 部署新应用程序时,Rails 不知道何时检查视图模板是否已更改。 如果我们更新我们的任务列表视图部分:

<% # app/views/tasks/_incomplete_tasks.html.erb %>
<% cache task do %>
    Task: <%= task.title %>
    Due Date: <%= task.due_date %>
    <p><%= task.notes %></p>
<% end %>

Rails 不会使使用局部视图的缓存片段过期。 在您必须将版本号添加到 cache 语句之前,但现在有一个名为 cache_digests 的 gem,它会自动将模板文件的 MD5 哈希添加到缓存键中。 如果更新部分并重新启动应用程序,缓存键将不再匹配,因为视图模板文件的 MD5 已更改,Rails 将再次呈现该模板。 它还处理模板文件之间的依赖关系,因此,在上面的示例中,如果 _incomplete_tasks.html.erb 更新,它将使依赖链上的所有缓存对象过期。

此功能自动包含在 Rails 4.0 版中。 要在 Rails 3 项目中使用此 gem,请输入以下命令:

gem install cache_digests

或者,如果您使用 Bundler,请将此行添加到您的 Gemfile:

gem 'cache_digests'

高级 Rails 和 Memcached 设置

Dalli Ruby Gem 非常强大,它负责在 memcached 服务器集群中传播密钥,从而分配负载并增加 memcached 容量。 如果您的 Web 层中有多个 Web 服务器,您可以在每个服务器上安装 memcached 并将它们全部添加到您的 config/environments/production.rb

config.cache_store = :dalli_store, 'web1.example.com', 'web2.example.com', 'web3.example.com'

这将使用 一致性哈希 将密钥分布在可用的 memcached 服务器上。

文章提交人:安德鲁·威廉姆斯