Sử Dụng Redis Cache Thông Minh Trong Node.js
Redis là key-value store siêu nhanh, thường được dùng làm cache layer cho backend. Nhưng nếu bạn chỉ biết .set()
và.get()
, thì bạn mới đang dùng Redis ở mức "cơ bản".
Trong bài này, mình sẽ chia sẻ cách sử dụng Redis thông minh hơn: tối ưu hiệu năng, tránh cache sai dữ liệu, và đảm bảo cache hoạt động hiệu quả khi traffic cao.
Tại sao nên dùng Redis?
- Tăng tốc độ phản hồi: dữ liệu trả về từ Redis có thể nhanh gấp 10–100 lần so với gọi DB.
- Giảm tải cho database: những truy vấn lặp lại nhiều lần không cần gọi lại.
- Giữ state cho nhiều instance: phù hợp với hệ thống có load balancer.
1. Cache theo key động (dynamic key)
Đừng dùng key tĩnh như 'user'. Hãy cache theo ID, query, hoặc session.
const key = `user:${userId}`;
const cached = await redis.get(key);
if (cached) {
return res.json(JSON.parse(cached));
}
const user = await db.getUserById(userId);
await redis.set(key, JSON.stringify(user), 'EX', 60 * 10); // cache 10 phút
return res.json(user);
2. Chỉ cache khi cần (cache selectively)
Không phải response nào cũng nên cache:
- Đừng cache data thay đổi liên tục (realtime, điểm số...)
- Đừng cache data chưa đầy đủ
if (user.isPremium) {
await redis.set(key, JSON.stringify(user), 'EX', 600);
}
3. Cache theo query string (pagination, filter)
Với các API có nhiều biến thể (filter, sort, page), bạn nên cache theo query:
const queryKey = `products:${req.query.category}-${req.query.page}`;
Lưu ý: cần chuẩn hóa query trước khi tạo key để tránh tạo quá nhiều bản ghi.
4. Sử dụng TTL và cache invalidation hợp lý
- EX: TTL (time-to-live) – chỉ cache trong một thời gian nhất định
- DEL: xoá cache khi dữ liệu bị thay đổi
- EXPIRE: cập nhật thời gian sống lại khi có update
wait redis.set('user:123', JSON.stringify(user), 'EX', 300); // cache 5 phút
// Khi user cập nhật thông tin:
await redis.del('user:123');
5. Dùng pipeline hoặc mget để giảm số roundtrip
Nếu cần lấy nhiều key cùng lúc:
const values = await redis.mget(['user:1', 'user:2', 'user:3']);
Hoặc khi set nhiều giá trị:
const pipeline = redis.pipeline();
items.forEach(item => {
pipeline.set(`item:${item.id}`, JSON.stringify(item), 'EX', 600);
});
await pipeline.exec();
6. Cache tầng 2 (Two-Level Cache)
- Level 1: Redis
- Level 2: In-memory (RAM trong process) Giúp xử lý nhanh gọn những request lặp lại liên tục trong cùng instance, tránh cả Redis overload.
Ví dụ (với node-cache
):
const localCache = new NodeCache();
let user = localCache.get(`user:${id}`);
if (!user) {
const redisData = await redis.get(`user:${id}`);
if (redisData) {
user = JSON.parse(redisData);
localCache.set(`user:${id}`, user, 30);
}
}
7. Cache dạng danh sách (list, sorted set)
Redis không chỉ lưu string. Bạn có thể cache top list, ranking, queue bằng zadd
, lpush
, lrange
.
// Top sản phẩm bán chạy
await redis.zadd('top-products', 100, 'product:123');
const top = await redis.zrevrange('top-products', 0, 9);
Kết
Redis không chỉ là “bộ nhớ tạm” – nếu biết cách dùng thông minh, bạn có thể:
- Tăng tốc API gấp 10 lần
- Giảm chi phí hạ tầng
- Giữ hệ thống ổn định ở mức tải cao
Tóm lại:
- Cache đúng: theo ID, query, TTL
- Cache đủ: dùng TTL, xóa khi cần
- Cache sạch: xóa khi update, dùng mget, pipeline, in-memory nếu hợp
All rights reserved