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的內存對一般的程序來說足夠
更多文章、技術交流、商務合作、聯系博主
微信掃碼或搜索:z360901061

微信掃一掃加我為好友
QQ號聯系: 360901061
您的支持是博主寫作最大的動力,如果您喜歡我的文章,感覺我的文章對您有幫助,請用微信掃描下面二維碼支持博主2元、5元、10元、20元等您想捐的金額吧,狠狠點擊下面給點支持吧,站長非常感激您!手機微信長按不能支付解決辦法:請將微信支付二維碼保存到相冊,切換到微信,然后點擊微信右上角掃一掃功能,選擇支付二維碼完成支付。
【本文對您有幫助就好】元
