redis_page

actionpack-page_caching 是将页面缓存到文件中,这样有两个缺点:

  1. nginx web 服务器需要访问到 app 服务器生成的文件;
  2. 多台 app 服务器都会生成自己的缓存文件,难以共享,NFS 等又不大稳定;

redis_page 改为将页面缓存至 redis,nginx 安装 redis 插件后即可直接使用。

Installation

Add this line to your application's Gemfile:

gem 'redis_page'

And then execute:

$ bundle

Usage

1. Config

增加文件:config/initializers/redis_page.rb

require "redis"
RedisPage.configure do |config|
  # 通过访问 http://cache:[email protected]:8081/products/1 来刷新缓存
  config.sweeper = { port: 8081, username: 'cache', password: 'ewHN84JZLyRurX' }
  config.redis = Redis.new(host: "redis", port: 6379, db: 10)
  config.ttl   = 604800    # 缓存 1 周后(默认)过期
end

Sidekiq.configure_server do |config|
  config.redis = { url: "redis://redis:6379/15" }
end

Sidekiq.configure_client do |config|
  config.redis = { url: "redis://redis:6379/15" }
end

2. Controller

生成页面缓存

class ProductController < ActionController::Base
  caches_redis_page :show                                            # 或者使用下面两行的格式
  #caches_redis_page :show, append_country: true                     # cache key 会在 path 后面加上国家代码,例如:/products-US
  #caches_redis_page :show, unless: Proc.new { params[:preview] }    # 带上 preview 参数,则不进行缓存,方便管理员对未保存的内容进行预览
  #caches_redis_page :show, namespace: 'www'                         # 多个子域名的 path 可能相同,可以使用 namespace 来区分

  def show
    @product = Product.find(params[:id])
  end
end

3. View

记录哪些实体更新时要刷新的 url,例如:iPhone 在首页中显示了,则记录下 iPhone 实体与首页的关联关系

- Product.all.each do |product|
  = @product.title

修改为:

- c(Product).all.each do |product|
  = c(@product).title

c 方法会记录当前页面 url, c(Product) 表示添加、删除商品也会刷新当前页面

4. Model

更新、删除、添加实体后刷新所有关联的页面缓存

class Product < ActiveRecord::Base
  include RedisPage::Sweeper
end

5. Collection

删除子记录时要触发父记录更新

collection.products.delete product

在父记录的 model 关系中增加 after_remove,触发父记录更新

  has_many :products, through: :collections_products, after_remove: proc { |a| a.touch }

异步任务

使用 Sidekiq 执行异步任务,默认的队列名为 redis_page

Contribution

gem build redis_page.gemspec
gem push redis_page-0.1.1.gem