Caching in Rails

1.Giới thiệu

Cache là tên gọi của bộ nhớ đệm – nơi lưu trữ các dữ liệu nằm chờ các ứng dụng hay phần cứng xử lý.Đối với ứng dụng web, Caching có tác dụng lưu giữ nội dung được tạo ra trong chu trình gửi yêu cầu - trả về phản hồi (request-response) và có thể tái sử dụng để trả về các response tương ứng đối với những request tương tự.Điều này giúp ích cho việc tăng tốc ứng dụng và cải thiện trải nghiệm người dùng rất nhiều. Ở bài này, mình sẽ giới thiệu một số kiểu caching sau:

  • page caching
  • action caching
  • fragment caching
  • sql caching

2.Page caching.

Để đặt chế độ caching, ta cần dòng config sau trong mỗi trường mà ta sử dụng:

config.action_controller.perform_caching = true

Trong Rails, fragment caching được cung cấp mặc định, để có thể sử dụng được các loại caching khác, ta cần sử dụng gem: 'actionpack-page_caching' . Dòng config sau sẽ giúp ta quyết định nơi được lưu giữ cached page.

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

Đối với Page caching, toàn bộ HTML của trang sẽ được lưu tại thư mục mà ta setting ở phía trên.Khi người dùng request lại trang này, Rails sẽ trả về luôn trang được lưu mà không cần thông qua render view một lần nữa.Điều này giúp cho việc tăng tốc độ ứng dụng lên rất nhiều.Tuy nhiên, chính việc trả về trực tiếp file HTML làm cho Page cahing không thể sử dụng được cho những trang cần xác thực người dùng, nó chỉ thực sự hữu ích khi sử dụng cho các trang tĩnh.

Để sử dụng page caching, ta cần thêm cài đặt sau vào controller:

caches_page :action_name

Dòng cài đặt trên thông báo cho Rails biết action nào sẽ được sử dụng page caching. Ví dụ:

class UsersController < ApplicationController
  caches_page :index
  
  def index
  end
end

Khi bạn tạo user mới và muốn trang index đươc load lại với dữ liệu mới này chứ không sử dụng trang HTML đã được lưu trước đó, ta sử dụng cài đặt sau trong hàm create:

expire_page action: 'index'

Ví dụ:

class UsersController < ApplicationController
  caches_page :index
  
  def index
  end
  
  def create
      expire_page action: 'index'
  end
end

3.Action caching.

Action caching giúp ta khắc phục được nhược điểm của page caching là không sử dụng được với những trang cần xác thực người dùng.Thay vì việc mọi request đều không được chạy qua Action Pack, thì action vẫn sẽ được chạy trước khi việc cache được thực hiện và vẫn được thực hiện bởi cách gọi before_action. Ví dụ:

class UsersController < ApplicationController
  before_action :authenticate, except :  :public

  caches_page   :public
  caches_action :index, :show
end

Action caching sử dụng fragment caching kết hợp với 1 call back, sau đây là 1 số lựa chọn khi gọi caches_action :

  • if hoặc unless để lựa chọn khi nào việc cache action được thực hiện.
  • expires_in để set khoảng thời gian thực hiện việc cache, ví du:
    caches_action :show, :expires_in => 1.hour
    
  • cache_path lựa chọn path để thực hiện cache, điều này hữu ích cho việc cache một action có nhiều lựa chọn cho path:
    caches_action :lists, :cache_path => proc do
        params[:user_id].present? user_list_url(params[:user_id, params[:id]) :  list_url(params[:id])
    end
    
  • layout nếu được set là false, việc cache sẽ chỉ được thực hiện với nội dung của action, nó hữu dụng cho những layout có nội dung động.
  • format được sử dụng khi action response có nhiều kiểu format khác nhau.

3.Fragment caching.

Đúng như tên gọi của nó, fragment caching thực hiện cache một phần của view, khi request gọi đến, action được gọi vẫn được xử lý bình thường cho tới khi HTML được sinh ra thì mới thực hiện cache lại 1 phần của nội dung HTML ấy.Việc này tiện dụng cho ta cache lại những phần nội dung tĩnh của trang web, ví dụ như thanh menu chẳng hạn:

<% cache('left_nav_bar') do %>
  <%= display_left_nav_bar %>
<% end %>

Đã có bài viết này khá chi tiết về fragment caching trên Viblo, mọi người có thể tham khảo.

4. SQL caching.

Mặc định trong Rails, đối với cùng 1 query được gọi nhiều lần, thì chỉ có lần gọi đầu tiên là Rails sẽ thực hiện truy vấn đến Database để truy xuất kết quả,từ lần thứ 2 trở đi, khi query được gọi thì kết quả của query được lưu trong bộ nhớ sẽ được sử dụng để trả ra kết quả.