`
hideto
  • 浏览: 2651449 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

Rails Cache

    博客分类:
  • Ruby
阅读更多
今天插一脚,介绍一下Rails的缓存机制以及memcached的使用
Rails的Cache分四种:
1,Page Cache - Fastest
2,Action Cache - Next Fastest
3,Fragment Cache - Least Fastest
4,ActiveRecord Cache - Only available in Edge Rails
下面一一介绍上面四种Cache以及Rails如何使用memcached

一、Page Cache
如果开发阶段要使用cache,则需要先设置好config/environments/development.rb:
config.action_controller.perform_caching = true

而production环境下默认是开启cache功能的
Page Cache是Rails中最快的cache机制,使用Page Cache的前提一般为:
1,需要cache的page对所有用户一致
2,需要cache的page对public可访问,不需要authentication
Page Cache使用起来很简单:
class BlogController < ApplicationController
  caches_page :list, :show

  def list
    Post.find(:all, \:order => "created_on desc", :limit => 10)
  end

  def show
    @post = Post.find(params[:id])
  end
end

这样我们就对BlogController的list和show页面进行了缓存
这样做的效果是第一次访问list和show页面时生成了public/blog/list.html和public/blog/show/5.html这两个html页面
对于分页情况下的cache,我们需要把url的page参数改写成"blog/list/:page"这种形式,而不是"blog/list?page=1"这种形式
这样cache的html页面即为public/blog/list/1.html
当数据更改时我们需要清除旧的缓存,我们采用Sweepers来做是非常不错的选择,这把在BlogController里清除缓存的代码分离出来
首先编辑config/environment.rb:
Rails::Initializer.run do |config|
  # ...
  config.load_paths += %w(#{RAILS_ROOT}/app/sweepers)
  # ...

这告诉Rails加载#{RAILS_ROOT}/app/sweepers目录下的文件
我们为BlogController定义app/sweepers/blog_sweeper.rb:
class BlogSweeper < ActionController::Caching::Sweeper
  observe Post # This sweeper is going to keep an eye on the Post model

  # If our sweeper detects that a Post was created call this
  def after_create(post)
    expire_cache_for(post)
  end

  # If our sweeper detects that a Post was updated call this
  def after_update(post)
    expire_cache_for(post)
  end

  # If our sweeper detects that a Post was deletedcall this
  def after_destroy(post)
    expire_cache_for(post)
  end

  private
  def expire_cache_for(record)
    # Expire the list page now that we posted a new blog entry
    expire_page(:controller => 'blog', :action => 'list')

    # Also expire the show page, in case we just edit a  blog entry
    expire_page(:controller => 'blog', :action => 'show', :id => record.id)
  end
end

然后我们在BlogController里加上该sweeper即可:
class BlogController < ApplicationController
  caches_page :list, :show
  cache_sweeper :blog_sweeper, \:only => [:create, :update, :destroy]
  # ...
end

我们可以配置cache的静态html文件的存放位置,这在config/environment.rb里设置:
config.action_controller.page_cache_directory = RAILS_ROOT + "/public/cache/"

然后我们设置Apache/Lighttpd对于静态html文件render时不接触Rails server即可
所以Page Cache就是最快的Cache,因为它不与Rails server打交道,直接load静态html

二、Action Cache
Action Cache相关的helper方法是caches_action和expire_action,其他基本和Page Cache一样
另外我们还可以运行rake tmp:cache:clear来清空所有的Action Cache和Fragment Cache
class BlogController < ApplicationController
  before_filter :authentication
  caches_action :list, :show
  cache_sweeper :blog_sweeper, \:only => [:create, :update, :destroy]

如上代码所示,我们将authentication这个filter放在caches_action之前声明,这样我们的Action Cache在执行之前会先访问authentication方法
这样可以弥补Page Cache不能对需要登录认证的Page进行Cache的缺点
生成的cache文件为tmp/cache/localhost:3000/blog/list.cache,这样对不同subdomain的访问页面可以cache到不同的目录
由于每次访问Action Cache时都需要与Rails server打交道,并且要先运行filters,所以比Page Cache的效率稍低

三、Fragment Cache
Fragment Cache用于处理rhtml页面中的部分需要cache的模块,如app/views/blog/list.rhtml:
<strong>My Blog Posts</strong>
<% cache do %>
  <ul>
    <% for post in @posts %>
      <li><%= link_to post.title, :controller => 'blog', :action => 'show', :id => post %></li>
    <% end %>
  </ul>
<% end %>

生成的cache文件为/tmp/cache/localhost:3000/blog/list.cache
我们需要在BlogController的list方法里加上一行判断,如果是读取Fragment Cache,则不必再查询一次数据库:
def list
  unless read_fragment({})
    @post = Post.find(:all, \:order => 'created_on desc', :limit => 10)
  end
end

Fragment分页时的Cache:
def list
  unless read_fragment({:page => params[:page] || 1}) # Add the page param to the cache naming
    @post_pages, @post = paginate :posts, :per_page => 10
  end
end

rhtml页面也需要改写:
<% cache ({:page => params[:page] || 1}) do %>
  ... All of the html to display the posts ...
<% end %>

生成的cahce文件为/tmp/cache/localhost:3000/blog/list.page=1.cache
从分页的Fragment Cache可以看出,Fragment Cache可以添加类似名字空间的东西,用于区分同一rhtml页面的不同Fragment Cache,如:
cache ("turkey") => "/tmp/cache/turkey.cache"
cache (:controller => 'blog', :action => 'show', :id => 1) => "/tmp/cache/localhost:3000/blog/show/1.cache"
cache ("blog/recent_posts") => "/tmp/cache/blog/recent_posts.cache"
cache ("#{request.host_with_port}/blog/recent_posts") => "/tmp/cache/localhost:3000/blog/recent_posts.cache"

清除Fragment Cache的例子:
expire_fragment(:controller => 'blog', :action => 'list', :page => 1)
expire_fragment(%r{blog/list.*})


四、ActiveRecord Cache
Rails Edge中ActiveRecord已经默认使用SQl Query Cache,对于同一action里面同一sql语句的数据库操作会使用cache

五、memcached
越来越多的大型站点使用memcached做缓存来加快访问速度
memcached是一个轻量的服务器进程,通过分配指定数量的内存来作为对象快速访问的cache
memcached就是一个巨大的Hash表,我们可以存取和删除key和value:
@tags = Tag.find :all
Cache.put 'all_your_tags', @tags
Cache.put 'favorite_skateboarder', 'Tom Penny'
skateboarder = Cache.get 'favorite_skateboarder'
Cache.delete 'all_your_tags'

我们可以使用memcached做如下事情:
1,自动缓存数据库的一行作为一个ActiveRecord对象
2,缓存render_to_string的结果
3,手动存储复杂的数据库查询作为缓存
cached_model让我们轻松的缓存ActiveRecord对象,memcahed-client包含在cached_model的安装里,memcahed-client提供了缓存的delete方法
sudo gem install cached_model

我们在config/environment.rb里添加如下代码来使用memcached:
require 'cached_model'

memcache_options = {
  :c_threshold => 10_000,
  :compression => true,
  :debug => false,
  :namespace => 'my_rails_app',
  :readonly => false,
  :urlencode => false
}

CACHE = MemCache.new memcache_options
CACHE.servers = 'localhost:11211'

对于production环境我们把上面的代码挪到config/environments/production.rb里即可
然后让我们的domain model集成CachedModel而不是ActiveRecord::Base
class Foo < CachedModel
end

然后我们就可以使用memcached了:
all_foo = Foo.find :all
Cache.put 'Foo:all', all_foo
Cache.get 'Foo:all'

需要注意的几点:
1,如果你查询的item不在缓存里,Cache.get将返回nil,可以利用这点来判断是否需要重新获取数据并重新插入到缓存
2,CachedModel的记录默认15分钟后expire,可以通过设置CachedModel.ttl来修改expiration time
3,手动插入的对象也会过期,Cache.put('foo', 'bar', 60)将在60秒后过期
4,如果分配的内存用尽,则older items将被删除
5,可以对每个app server启动一个memcached实例,分配128MB的内存对一般的程序来说足够

注:本文参考Ruby on Rails Caching Tutorialmemcached Basics for Rails两篇网文
BTW:Rails Envy上面有几个Ruby On Rails的广告视频,是关于与PHP/Java的比较,比较生动搞笑
分享到:
评论
3 楼 blackanger 2007-06-09  
我是模仿你的  
2 楼 hideto 2007-06-09  
你的也不错
1 楼 blackanger 2007-06-09  
hideto大哥的头像就是个性

相关推荐

    second_level_cache:受CacheMoney和cache_fu启发的直写和直读缓存库,支持ActiveRecord 4、5和6

    SecondLevelCache是​​一个受Cache Money和cache_fu启发的直写式和直读式缓存库,支持ActiveRecord 4,ActiveRecord 5和ActiveRecord 6。 直读:按ID进行的查询,例如current_user.articles.find(params[:id]) ,...

    rails-cache-inspector:用于片段缓存的可视化调试的简单工具

    安装将此行添加到应用程序的Gemfile中: gem 'rails-cache-inspector' , group : :development用法配置突出显示 # config/initializers/rails_cache_inspector.rbRailsCacheInspector . configuration . highlight_...

    rails-cache-extended:帮助程序和日志记录添加到 Rails 缓存

    Rails::Cache::Extended 这允许为记录集合生成自动过期的缓存键 安装 将此行添加到应用程序的 Gemfile 中: gem 'rails-cache-extended' 然后执行: $ bundle 或者自己安装: $ gem install rails-cache-...

    Rails.Angular.Postgres.and.Bootstrap.2nd.Edition

    Cache Complex Queries Using Materialized Views Chapter 11. Asynchronously Load Data from Many Sources Chapter 12. Wrangle Forms and Validations with Angular Chapter 13. Dig Deeper Appendix A1. Full ...

    model_cache:用于缓存模型代码的 Rails 插件

    模型缓存ModelCache 是一个简单的 Rails 缓存插件,使用memcached 。 它为您的模型提供缓存功能,允许: 基于通用键(ActiveRecord cache_key在幕后添加)在模型实例方法中缓存代码块缓存您的实例方法,可选择使用...

    redis-rails:Ruby on Rails的Redis存储

    Ruby on Rails的Redis商店 redis-rails为Ruby on Rails提供了一整套存储(缓存,会话, HTTP缓存)。 有关一般准则,请参见主要的。 关于Rails 5.2的快速说明 ... cache_store = :redis_store , "re

    Secode_level_cache.zip

    Rails的ActiveRecord自身没有带强大的对象缓存功能,这是AR的一个重大的遗憾。早在2008年开始,我们就借鉴了Java强大的ORM 框架Hibernate的二级对象缓存编写了这个Rails的AR对象缓存插件,并且一直作为JavaEye网站...

    针:在Rails中创建微服务,只需最少的仪式

    只需编写常规的Rails代码,即可在Rails中创建微服务。 该宝石提供: 透明的API密钥身份验证。 基于标头的路由器级API版本。 通过验收测试记录微服务端点的方法。 结构化错误,可以从无效的Active Record,异常...

    has_cache:Rails 缓存存储的便利包装器

    包括has_cache在Rails项目Gemfile : gem 'has_cache' 在类中调用has_cache ,例如在模型中: class User &lt; ActiveRecord :: Base has_many :posts , inverse_of : :user has_cache end class Post &lt; ...

    Ruby-RecordCache在Rails3中缓存ActiveModelRecords

    Record Cache - 在Rails 3中缓存Active Model Records

    在Ruby on Rails上使用Redis Store的方法

    此外,在Ruby on Rails上使用它也是非常的简单。  如何使用: 对于在Rails上使用Redis Store,首先我们需要在Gemfile文件中添加入口   gem 'redis-rails' gem 'redis-rack-cache' # optional 然后我们就会有...

    join_cache:使用Rails缓存加快ActiveRecord关联

    join_cache 使用Rails缓存可以更快地进行ActiveRecord关联。 什么? 假设您搭建了Rails应用并最终得到了以下结果: class Employee &lt; ActiveRecord xss=removed&gt; Team Load SELECT "teams" . * FROM "teams" ...

    counter_culture:Rails应用程序的涡轮增压计数器缓存

    反文化 Turbo为您的Rails应用程序提供计数器缓存。 对Rails标准计数器缓存的巨大改进...product.categories_count # =&gt; will use counter cache without query 安装 将counter_culture添加到您的Gemfile中: gem 'co

    cache_manager:Rails Engine管理您的缓存存储

    缓存管理器可安装的Rails引擎可查看您的缓存并管理密钥/清理缓存。 注意:当前已通过文件存储和Redis缓存存储进行测试。安装在您的Gemfile中添加宝石 gem 'cache_manager' 和捆绑$ bundle install 安装后,将引擎...

    rspec-console:在rails控制台中运行RSpec测试

    确保在config / environment / test.rb文件中关闭了Rails的cache_classes : Rails . application . configure do # turn off this! config . cache_classes = false end 3)启动控制台 使用Rails,使用rails c ...

    enterprise_rails.pdf

    “This Rails Application Is the Only Application on Earth” 43 Sit Atop the Shoulders of Giants 43 Choosing the Right RDBMS 44 A Note on Migrations 44 Dispelling Myths 46 Operations and Reporting 47 5...

    easy_captcha:验证码插件(Rails)

    EasyCaptcha 基于rmagick的rails 3的简单验证码实现 经过Rails 3.2.8的测试 安装 添加到Gemfile gem 'easy_captcha' ... # Cache temp dir from Rails.root # config.cache_temp_dir = Rails.root

Global site tag (gtag.js) - Google Analytics