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:
而production环境下默认是开启cache功能的
Page Cache是Rails中最快的cache机制,使用Page Cache的前提一般为:
1,需要cache的page对所有用户一致
2,需要cache的page对public可访问,不需要authentication
Page Cache使用起来很简单:
这样我们就对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加载#{RAILS_ROOT}/app/sweepers目录下的文件
我们为BlogController定义app/sweepers/blog_sweeper.rb:
然后我们在BlogController里加上该sweeper即可:
我们可以配置cache的静态html文件的存放位置,这在config/environment.rb里设置:
然后我们设置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
如上代码所示,我们将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:
生成的cache文件为/tmp/cache/localhost:3000/blog/list.cache
我们需要在BlogController的list方法里加上一行判断,如果是读取Fragment Cache,则不必再查询一次数据库:
Fragment分页时的Cache:
rhtml页面也需要改写:
生成的cahce文件为/tmp/cache/localhost:3000/blog/list.page=1.cache
从分页的Fragment Cache可以看出,Fragment Cache可以添加类似名字空间的东西,用于区分同一rhtml页面的不同Fragment Cache,如:
清除Fragment Cache的例子:
四、ActiveRecord Cache
Rails Edge中ActiveRecord已经默认使用SQl Query Cache,对于同一action里面同一sql语句的数据库操作会使用cache
五、memcached
越来越多的大型站点使用memcached做缓存来加快访问速度
memcached是一个轻量的服务器进程,通过分配指定数量的内存来作为对象快速访问的cache
memcached就是一个巨大的Hash表,我们可以存取和删除key和value:
我们可以使用memcached做如下事情:
1,自动缓存数据库的一行作为一个ActiveRecord对象
2,缓存render_to_string的结果
3,手动存储复杂的数据库查询作为缓存
cached_model让我们轻松的缓存ActiveRecord对象,memcahed-client包含在cached_model的安装里,memcahed-client提供了缓存的delete方法
我们在config/environment.rb里添加如下代码来使用memcached:
对于production环境我们把上面的代码挪到config/environments/production.rb里即可
然后让我们的domain model集成CachedModel而不是ActiveRecord::Base
然后我们就可以使用memcached了:
需要注意的几点:
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的内存对一般的程序来说足够
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
- deflist
- Post.find(:all,\:order=> "created_ondesc" ,:limit=> 10 )
- end
- defshow
- @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
- observePost#ThissweeperisgoingtokeepaneyeonthePostmodel
- #IfoursweeperdetectsthataPostwascreatedcall this
- defafter_create(post)
- expire_cache_for(post)
- end
- #IfoursweeperdetectsthataPostwasupdatedcall this
- defafter_update(post)
- expire_cache_for(post)
- end
- #IfoursweeperdetectsthataPostwasdeletedcall this
- defafter_destroy(post)
- expire_cache_for(post)
- end
- private
- defexpire_cache_for(record)
- #Expirethelistpagenowthatweposteda new blogentry
- expire_page(:controller=> 'blog' ,:action=> 'list' )
- #Alsoexpiretheshowpage,in case wejusteditablogentry
- 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>MyBlogPosts</strong>
- <%cache do %>
- <ul>
- <% for postin @posts %>
- <li><%=link_topost.title,:controller=> 'blog' ,:action=> 'show' ,:id=>post%></li>
- <%end%>
- </ul>
- <%end%>
生成的cache文件为/tmp/cache/localhost:3000/blog/list.cache
我们需要在BlogController的list方法里加上一行判断,如果是读取Fragment Cache,则不必再查询一次数据库:
- deflist
- unlessread_fragment({})
- @post =Post.find(:all,\:order=> 'created_ondesc' ,:limit=> 10 )
- end
- end
Fragment分页时的Cache:
- deflist
- unlessread_fragment({:page=>params[:page]|| 1 })#Addthepageparamtothecachenaming
- @post_pages , @post =paginate:posts,:per_page=> 10
- end
- end
rhtml页面也需要改写:
- <%cache({:page=>params[:page]|| 1 }) do %>
- ...Allofthehtmltodisplaytheposts...
- <%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' , 'TomPenny'
- 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方法
- sudogeminstallcached_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的内存对一般的程序来说足够