Rails Model Caching with Redis
Bài đăng này đã không được cập nhật trong 8 năm
Model level caching hay bị các developers bỏ qua, ngay cả các developers dày dặn kinh nghiệm. Phần lớn là do quan niệm sai lầm. Cache cấp độ thấp rất linh hoạt và bạn có thể làm việc với nó ở bất cứ ứng dụng nào. Trong hướng dẫn này, tôi sẽ chỉ cho bạn cách dùng cache cho models của Rails bằng Redis.
Cache hoạt động như thế nào?
Bình thường ta truy cập trực tiếp vào ổ đĩa để lấy dữ liệu, điều này khiến ứng dụng của bạn sẽ cần đến một ổ đĩa tốt đắt tiền để làm cho ứng dụng của bạn chạy êm mượt. Nhưng liên tục truy cập như thế sẽ khiến hiệu suất sẽ giảm. Để xử lý điều này ta xậy dựng 1 layer giữa ứng dụng của bạn với database được lưu trên ổ đĩa, được gọi là bộ nhớ cache. Bộ nhớ cache không lưu trữ dữ liệu ngay từ đầu mà khi ta request tới ứng dụng để lấy data trong database, bộ nhớ cache sẽ lưu trữ những dự liệu này để dụng cho các phiên làm việc tiếp theo từ đó sẽ giúp ứng dụng chúng ta không mất nhiều thời gian để lấy data trong database nữa, từ đó cải thiện hiệu suất của ứng dụng.
Tại sao lại là Redis?
Redis là một bố nhớ, theo kiểu key-value. Nó có tốc độ truy cập nhanh, và lấy dữ liệu ra gần như là tức thời. Redis hỗ trợ rất nhiều các cấu trúc dữ liệu khác nhau như: list, hash... Redis rất dễ dàng trong việc cài đặt và sử dụng. Nếu bạn sử dụng resque
hoặc sidekiq
trong việc quản lý các jobs chạy ngầm thì bạn đang có Redis được cài đặt sẵn.
Cách cài đặt
Chúng ta sẽ download redis và make nó:
$ wget http://download.redis.io/releases/redis-2.8.18.tar.gz
$ tar xzf redis-2.8.18.tar.gz
$ cd redis-2.8.18
$ make
Sau khi chạy những cậu lệnh ở trên ta chờ cho source redis biên dịch xong. Chúng ta sẽ chạy tiếp câu lệnh ở dưới:
$ cd redis-2.8.18/src
$ ./redis-server
Cài đặt Redis vào Rails
Add những gem vào Gemfile
gem 'redis'
gem 'redis-namespace'
gem 'redis-rails'
gem 'redis-rack-cache'
Chúng ta sẽ khai báo cho Rails để sử dụng Redis như một bộ nhớ cache:
# config/application.rb
#...........
config.cache_store = :redis_store, 'redis://localhost:6379/0/cache', { expires_in: 90.minutes }
#.........
Dưới đây là ví dụ cách các bạn lưu trữ dữ liệu vào Redis:
# lưu trữ dữ liệu
$redis.set("test_key", "Hello World!")
# lấy dữ liệu ra
$redis.get("test_key")
Chúng ta đã có những kiến thức cơ bản về Redis, giờ hãy bắt đầu viết 1 hàm helpers:
# app/helpers/category_helper.rb
module CategoryHelper
def fetch_categories
categories = $redis.get("categories")
if categories.nil?
categories = Category.all.to_json
$redis.set("categories", categories)
end
@categories = JSON.load categories
end
end
Ở thời điểm đầu tiên ta chưa có dữ liệu nào trong bộ nhớ cache. Bởi vậy chúng ta sẽ request tới database để lấy dự liệu rồi sau đó lưu chúng vào Redis. Khi ta lưu 1 đối tượng nào đó vào Redis, chúng ta có 2 lựa chọn. Thứ nhất ta sẽ duyệt qua từng phần tử của dự liệu rồi lưu chúng dưới dạng Hash, nhưng cách này rất chậm. Cách đơn giản hơn là chúng ta sẽ lưu chúng dưới dạng JSON. Và từ đó dữ liệu lấy ra chúng ta chỉ cần JSON.load
nó.
Để quản lý những dữ liệu sẽ được lưu trữ trong bao lâu ta sẽ sử dụng $redis.expire
# app/helpers/category_helper.rb
module CategoryHelper
def fetch_categories
categories = $redis.get("categories")
if categories.nil?
categories = Category.all.to_json
$redis.set("categories", categories)
# Expire the cache, every 3 hours
$redis.expire("categories",3.hour.to_i)
end
@categories = JSON.load categories
end
end
Như code ở trên chúng ta thấy dữ liệu được lưu trữ trong vòng 3 tiếng mới được xóa, bởi vậy nếu trong 3 tiếng đó nếu có 1 category nào được thêm hoặc update hoặc xóa thì dữ liệu được lấy ra để hiển thị sẽ không còn đúng. Chúng ta sẽ thêm 1 callback
trong model để mỗi khi update, create or delete thì dữ liệu trong redis luôn luôn là dự liệu chuẩn của Database:
# app/models/category.rb
class Category
#...........
after_save :clear_cache
def clear_cache
$redis.del "categories"
end
#...........
end
Kết luận
Trên đây là bài giới thiệu tổng quan về bộ nhớ đệm cache cấp thấp. Nó rất đơn giản và dễ sử dụng. Hy vọng bài viết sẽ giúp các bạn lập trình đơn giản và linh hoạt hơn
All rights reserved