Giới thiệu vấn đề
API đọc dữ liệu thường gặp nghẽn cổ chai khi truy vấn cơ sở dữ liệu trực tiếp. Khi số lượng yêu cầu tăng, thời gian phản hồi có thể vượt quá 200ms, gây trải nghiệm kém cho người dùng.
Nguyên lý hoạt động của Redis Cache
Redis lưu trữ dữ liệu trong bộ nhớ RAM, cho phép truy xuất O(1). Khi một truy vấn được thực hiện lần đầu, kết quả sẽ được ghi vào Redis. Các yêu cầu tiếp theo sẽ lấy dữ liệu từ cache, giảm tải DB và thời gian phản hồi.
Cài đặt Redis trong dự án Express
Cài redis và util để sử dụng async/await với các hàm callback.
npm install redis
Khởi tạo client Redis.
const redis = require('redis');
const { promisify } = require('util');
const client = redis.createClient({
host: '127.0.0.1',
port: 6379
});
const getAsync = promisify(client.get).bind(client);
const setAsync = promisify(client.setex).bind(client);
Middleware cache cho route GET
Middleware kiểm tra Redis trước khi gọi DB.
async function cache(req, res, next) {
const key = `users:${req.query.page || 1}`;
try {
const cached = await getAsync(key);
if (cached) {
return res.json(JSON.parse(cached));
}
res.locals.cacheKey = key;
next();
} catch (err) {
console.error('Redis error:', err);
next();
}
}
Route sử dụng cache
Ghi kết quả vào Redis sau khi lấy từ DB, thời gian hết hạn 60 giây.
app.get('/api/users', cache, async (req, res) => {
const page = parseInt(req.query.page) || 1;
const limit = 20;
const users = await User.find()
.skip((page - 1) * limit)
.limit(limit)
.lean();
// Lưu vào cache
await setAsync(res.locals.cacheKey, 60, JSON.stringify(users));
res.json(users);
});
Chiến lược invalidation
Cache cần được xóa khi dữ liệu thay đổi. Thêm hàm xóa cache trong các route tạo, cập nhật, xóa.
async function clearUserCache() {
const keys = await promisify(client.keys).bind(client)('users:*');
if (keys.length) {
await promisify(client.del).bind(client)(keys);
}
}
app.post('/api/users', async (req, res) => {
const newUser = await User.create(req.body);
await clearUserCache();
res.status(201).json(newUser);
});
Kiểm tra hiệu năng
Sử dụng ab hoặc wrk để đo thời gian phản hồi trước và sau khi bật cache.
ab -n 1000 -c 50 http://localhost:3000/api/users?page=1
Kết quả thường giảm thời gian trung bình từ ~180ms xuống ≈30ms khi cache hit.
Kết luận
Áp dụng Redis cache cho các endpoint đọc giảm tải DB, cải thiện thời gian phản hồi, hỗ trợ mở rộng hệ thống. Đối với các trường hợp ghi nhiều, cần thiết kế chiến lược invalidation phù hợp.
Muốn nắm vững toàn bộ kiến thức Backend Node.js, từ Core đến Redis, Queue, Security, hãy Tham khảo khóa học "Lập trình Back-End với NodeJS Express" tại đây.




.png)



