Tăng tốc Rails với data model cache sử dụng gem IdentityCache
Bài đăng này đã không được cập nhật trong 7 năm
1. Giới thiệu
Khi model ngày càng trở nên phức tạp, và yêu cầu cho response data từ controller hay API vẫn phải đảm bảo trong 1 giới hạn thời gian cho phép, giải pháp dễ dàng nhất là thực hiện preload, sử dụng includes để giảm bớt một số lượng lớn câu SQL.
Tuy nhiên, model lại tiếp tục phức tạp hơn, preload không còn đáp ứng được, tới đây ta nghĩ đến cache response cho mỗi request. Nhưng phương pháp cache này sẽ làm mất các object includes.
Từ đó, với mong muốn vẫn cache model, vẫn giữ các includes và cung cấp khả năng xử lý các object thông qua cache, gem IdentityCache sẽ đáp ứng các khả năng trên.
2. Model cache với IdentityCache
1. Cài đặt và cấu hình
Thêm vào trong gem file và chạy bundle
gem 'identity_cache'
Thêm config trong file môi trường:
config.identity_cache_store = :mem_cache_store, Memcached::Rails.new(:servers => ["mem1.server.com"])
2. Cách dùng
IdentityCache thêm hàm fetch_*
cho class mà ta dùng để cache với các index đã được định nghĩa trong class.
- sử dụng
fetch_by_(index)
với index của 1 field - sử dụng
fetch_(association)
với index của association
Ví dụ: ta muốn lấy các object image của product đã được cache
# định nghĩa model product.rb
# include IdentityCache trong model cần cache
class Product < ActiveRecord::Base
include IdentityCache
has_many :images
cache_has_many :images, :embed => true
end
# get product theo id
@product = Product.fetch(id)
# lấy image từ product, image đã được gắn kèm nên khi product được load thì image cũng được load theo
@images = @product.fetch_images
IdentityCache cho phép tìm kiếm theo các trường khác ngoài id. Bạn có thể tạo nhiều index bằng cách kết hợp nhiều trường:
class Product < ActiveRecord::Base
include IdentityCache
cache_index :handle, :unique => true
cache_index :vendor, :product_type
end
# Lấy product từ cache với index
# Nếu object không nằm trong cache, nó sẽ được tìm kiếm trong db và sẽ tự lưu vào trong cache
product = Product.fetch_by_handle(handle)
products = Product.fetch_by_vendor_and_product_type(vendor, product_type)
Với cache_has_many
và cache_has_one
, ta có thể dễ dàng thực hiện includes
trong cache, khi load parent object thì sẽ thực hiện load toàn bộ object quan hệ với nó với cú pháp fetch_(association)
_ vd : @product.fetch_images
Trong trường hợp object không được cache, product và nhưng object quan hệ sẽ được load từ trong db. Sau đó data sẽ được tự động lưu thành 1 key của product trong cache, và những lần request sau thì ta chỉ cần gọi @product.fetch_images
để lấy product và image sẽ được load cùng từ cache, không cần phải request đến db.
3. Kết luận
Với IdentityCache, việc sử dụng cache cho model nhưng vẫn có thể dùng preload cho object cache đã trở nên rất đơn giản.
Để có thể tìm hiểu rõ hơn về IdentityCache, bạn có thể dựa theo các nguồn tham khảo bên dưới:
All rights reserved