在线观看不卡亚洲电影_亚洲妓女99综合网_91青青青亚洲娱乐在线观看_日韩无码高清综合久久

鍍金池/ 教程/ Ruby/ 6.2 緩存
寫(xiě)在后面
寫(xiě)在前面
第六章 Rails 的配置及部署
第四章 Rails 中的模型
4.4 模型中的校驗(yàn)(Validates)
1.3 用戶(hù)界面(UI)設(shè)計(jì)
6.5 生產(chǎn)環(huán)境部署
3.2 表單
4.3 模型中的關(guān)聯(lián)關(guān)系(Relations)
4.5 模型中的回調(diào)(Callback)
第五章 Rails 中的控制器
4.2 深入模型查詢(xún)
5.2 控制器中的方法
6.2 緩存
3.4 模板引擎的使用
6.4 I18n
第一章 Ruby on Rails 概述
6.6 常用 Gem
1.2 Rails 文件簡(jiǎn)介
2.2 REST 架構(gòu)
2.3 深入路由(routes)
第三章 Rails 中的視圖
6.3 異步任務(wù)及郵件發(fā)送
第二章 Rails 中的資源
3.3 視圖中的 AJAX 交互

6.2 緩存

概要:

本課時(shí)講解 Rails 中如何使用緩存。

知識(shí)點(diǎn):

  1. 緩存
  2. redis
  3. memcached

正文

6.2.1 Rails 緩存

Rails 提供了三種方式的緩存,頁(yè)面緩存,方法緩存和片段緩存,在 Rails 4 之前的版本里,它包含在 Rails 中,但是從 4.x 開(kāi)始,三種緩存中的兩種轉(zhuǎn)為 gem 形式,只有片段緩存保留在 Rails 默認(rèn) 中。

在開(kāi)發(fā)環(huán)境下,緩存是關(guān)閉的,如果要測(cè)試它,需要更改配置:

config.action_controller.perform_caching = true

在產(chǎn)品環(huán)境下,它默認(rèn)是 true。

6.2.2 頁(yè)面緩存,Page Cache

Rails 4.x 將頁(yè)面緩存轉(zhuǎn)為 gem,使用的時(shí)候需要加入到 gemfile 中。

我們?cè)O(shè)置一下緩存路徑,在 config/environments/development.rb

config.action_controller.page_cache_directory = "#{Rails.root.to_s}/public"

頁(yè)面緩存是將整個(gè)頁(yè)面,生成一份靜態(tài)的 html 頁(yè)面,這個(gè)頁(yè)面會(huì)保存在剛才設(shè)置的目錄中。Rails 在顯示該地址的時(shí)候,會(huì)優(yōu)先查找 public 是否有同名的 html 文件優(yōu)先顯示。

我們把 show 方法加入到頁(yè)面緩存中:

class ProductsController < ApplicationController
  ...
  caches_page :show

當(dāng)?shù)谝淮卧L問(wèn)時(shí),會(huì)創(chuàng)建該緩存文件:

Write page /path/to/project/public/products/3.html (9.5ms)

再次訪問(wèn)時(shí),便直接讀取該文件,而不再執(zhí)行 show 方法了。

這樣做的好處是,可以把一些經(jīng)常訪問(wèn)的頁(yè)面作為頁(yè)面緩存。缺點(diǎn)是,這種頁(yè)面不能有太多用戶(hù)的個(gè)人信息,因?yàn)檫@個(gè)頁(yè)面對(duì)所有人訪問(wèn)都是相同的內(nèi)容。如果必須考慮個(gè)人信息,可以改為 js 形式,或者使用方法緩存(Action Cache)。

當(dāng)這個(gè)緩存頁(yè)面內(nèi)容更改時(shí),可以刪掉該文件,再次訪問(wèn)時(shí)會(huì)自動(dòng)創(chuàng)建。也可以在 update 內(nèi)加入過(guò)期的命令:

def update
  respond_to do |format|
    if @product.update(product_params)
      expire_page action: 'show', id: @product.id
      ...
    else
      ...
    end
  end
end

更新資料后會(huì)自動(dòng)過(guò)期該文件。

Expire page /path/to/project/public/products/3.html (1.0ms)

6.2.3 方法緩存,Action Cache

方法緩存和頁(yè)面緩存的區(qū)別是:它會(huì)執(zhí)行對(duì)應(yīng)的 action 中的代碼。頁(yè)面緩存直接讀取緩存文件,不執(zhí)行 action 中的代碼。

頁(yè)面緩存的 gem 在這里。

我們給方法增加方法緩存:

class ProductsController < ApplicationController
  ...
  caches_action :index, layout: false

訪問(wèn)該頁(yè)面,會(huì)創(chuàng)建一個(gè)片段緩存(fragment cache)文件:

Write fragment views/localhost:3000/products (5.9ms)

該片段緩存為當(dāng)前整個(gè)頁(yè)面,我們?cè)黾?layout: false 參數(shù),這樣,片段緩存只包含該 action 對(duì)應(yīng)的模板內(nèi)容,而不包含 layout。我們?cè)O(shè)計(jì)的代碼,將用戶(hù)信息放置在 layout 中,登錄后會(huì)顯示用戶(hù)名。所以 layout 是不應(yīng)該放到緩存中的。

但是,因?yàn)槲覀兘o index 方法增加了搜索功能,而該方法已經(jīng)加入到了緩存中,所以,搜索是還是顯示的緩存內(nèi)容。這里可以做調(diào)整,要么將搜索放到專(zhuān)用的非緩存方法中,要么搜索時(shí)過(guò)時(shí)該緩存。

6.2.4 片段緩存,F(xiàn)ragment Cache

片段緩存,是 Rails 默認(rèn)使用的緩存方式,它指的是視圖(view)中,緩存局部?jī)?nèi)容:

<% cache do %>
  分類(lèi):
  <% Catalog.all.each do |catalog| %>
    <%= link_to catalog.name, catalog %>
  <% end %>
<% end %>

這里把經(jīng)常訪問(wèn)的分類(lèi)列表,加入到了緩存中,避免每次頁(yè)面訪問(wèn)該部分都讀取數(shù)據(jù)庫(kù)。

我們可以給 cache 方法增加一些參數(shù):

<% cache(action: 'new', action_suffix: 'all_products') do %>

它產(chǎn)生的緩存 key 是:

Write fragment views/localhost:3000/products/new?action_suffix=all_products/02c540e3ab26f72d5e9273d5824c204e (60.0ms)

也可以直接命名緩存 key:

<% cache( "all_products" ) do %>

它產(chǎn)生的緩存 key 是:

Write fragment views/all_products/cc926a692262d0e538f07d5dd5d54942 (15.1ms)

或者直接緩存一個(gè)實(shí)例:

<% cache @product do %>

它產(chǎn)生的緩存 key 是:

Write fragment views/products/3-20150620164035711340000/b0699b1b8be94ebd1bfcfe74a21571f8 (21.5ms)

可見(jiàn),緩存是產(chǎn)生一個(gè) key: value 結(jié)構(gòu)的數(shù)據(jù)。key 來(lái)自于實(shí)例的 cache_key 方法:

p = Product.last
p.cache_key
 => "products/3-20150620164035711340000" 
p.updated_at = nil
p.cache_key
 => "products/3" 

該方法會(huì)讀取 updated_at 字段值,這樣,每當(dāng)該實(shí)例更改的時(shí)候,會(huì)自動(dòng)更新 updated_at 字段,相當(dāng)于自動(dòng)更新了緩存。

我們可以使用

expire_fragment(action: 'new', action_suffix: 'all_products')
expire_fragment("all_products")

過(guò)期這些片段緩存

6.2.5 緩存服務(wù)

緩存產(chǎn)生的是 key: value 結(jié)構(gòu)的數(shù)據(jù),所以我們可以使用支持該解構(gòu)的數(shù)據(jù)庫(kù)來(lái)保存緩存。在 config/environments/production.rb 中有 cache_store 的選項(xiàng):

# Use a different cache store in production.
config.cache_store = :mem_cache_store

這里有四個(gè)選項(xiàng)可以使用::memory_store, :file_store, :mem_cache_store, :null_store。在 手冊(cè)里還介紹了 JRuby 的 Ehcache。

6.2.5.1 :memory_store

緩存和 Ruby 進(jìn)程使用共同的內(nèi)存,默認(rèn)大小為32M,如果超出這個(gè)范圍,會(huì)移除掉舊的記錄。我們可以更改這個(gè)限制:

config.cache_store = :memory_store, { size: 64.megabytes }

但是多個(gè) Rails 應(yīng)用不會(huì)共享該緩存。它不適合大型的部署,適合小型的,低訪問(wèn)量的應(yīng)用。

6.2.5.2 :file_store

config.cache_store = :file_store, "/path/to/cache/directory"

緩存利用文件系統(tǒng)來(lái)存放緩存文件,雖然可以在多個(gè)應(yīng)用間共享緩存,但是不建議在產(chǎn)品環(huán)境下使用。這種方式會(huì)不斷的增加硬盤(pán)使用,直到手動(dòng)清空所有緩存。

Rails 默認(rèn)使用這種方式。

6.2.5.3 :mem_cache_store

這種方式使用 Memcached 最為后端緩存服務(wù),它提供了高性能的、集中式的緩存服務(wù),可以在多個(gè)應(yīng)用間共享緩存,這是一種適合中大型商業(yè)應(yīng)用的選擇。

config.cache_store = :mem_cache_store, "cache-1.example.com", "cache-2.example.com"

使用 Memcached 需要安裝 dalli,操作時(shí):

Rails.cache.read('key')
Rails.cache.write('key', value)
Rails.cache.fetch('key') { value }

6.2.5.4 :null_store

這是一種適合開(kāi)發(fā)和測(cè)試環(huán)境的配置,它不會(huì)儲(chǔ)存任何東西,但是可以正常調(diào)試 Rails.cache 中的方法。

config.cache_store = :null_store

6.2.5.5 自定義緩存服務(wù)

Redis 作為一個(gè)高性能的內(nèi)存型數(shù)據(jù)庫(kù),也可以作為緩存服務(wù)。我們先安裝 redis 的 gem:

gem 'redis-rails'
gem "hiredis"

增加配置:

config.cache_store = :redis_store, {
      host: 127.0.0.1,
      port: 6379,
      password: 123456,
      db: 1,
      namespace: "cache" }

現(xiàn)在,越來(lái)越多的 Rails 項(xiàng)目和 redis 配合使用,比如下一節(jié)要介紹的異步服務(wù),還有大量非結(jié)構(gòu)化的數(shù)據(jù),也可以?xún)?chǔ)存在 redis 中。比如站內(nèi)短信息,好友動(dòng)態(tài),或者好友列表,都可以通過(guò) redis 的命令快速實(shí)現(xiàn),較之關(guān)系型數(shù)據(jù)庫(kù)擁有更快的讀寫(xiě)速度,且更適合儲(chǔ)存非結(jié)構(gòu)化數(shù)據(jù)。

非結(jié)構(gòu)化數(shù)據(jù)庫(kù)是指其字段長(zhǎng)度可變,并且每個(gè)字段的記錄又可以由可重復(fù)或不可重復(fù)的子字段構(gòu)成的數(shù)據(jù)庫(kù),用它不僅可以處理結(jié)構(gòu)化數(shù)據(jù)(如數(shù)字、符號(hào)等信息)而且更適合處理非結(jié)構(gòu)化數(shù)據(jù)(全文文本、圖象、聲音、影視、超媒體等信息)。來(lái)自百度百科

6.2.6 緩存的讀取和寫(xiě)入

我們可以在 Rails 項(xiàng)目?jī)?nèi)部,使用 Rails.cache.fetch 來(lái)讀取緩存,如果不存在,將返回 nil,如果傳入 block,會(huì)將 block 中的結(jié)果寫(xiě)入緩存,并將其返回。比如:

class Product < ActiveRecord::Base
  def competing_price
    Rails.cache.fetch("#{cache_key}/competing_price", expires_in: 12.hours) do
      Competitor::API.find_price(id)
    end
  end
end

在 fetch 中可以設(shè)置過(guò)期時(shí)間。

更多 API 信息可以查看 這里。