Giới thiệu vấn đề
API GET thường chịu tải đọc cao, truy vấn DB trực tiếp gây latency >100ms và làm server bị nghẽn. Giải pháp: lưu kết quả truy vấn vào Redis, trả cache khi có yêu cầu tương tự.
Cài đặt Redis và client
Cài Redis server (Docker) và thư viện redis cho Node.js.
docker run -d --name redis -p 6379:6379 redis:6-alpine
Khởi tạo client trong dự án:
const redis = require('redis');
const client = redis.createClient({ url: 'redis://localhost:6379' });
client.connect().catch(console.error);Thiết kế hàm cache
Hàm cache nhận key, thời gian hết hạn và hàm truy vấn DB. Nếu key tồn tại, trả giá trị đã giải mã; nếu không, thực thi hàm DB, lưu vào Redis và trả kết quả.
async function cache(key, ttl, dbFn) {
const cached = await client.get(key);
if (cached) {
return JSON.parse(cached);
}
const result = await dbFn();
await client.setEx(key, ttl, JSON.stringify(result));
return result;
}Ví dụ với MongoDB
const User = require('./models/User');
app.get('/users/:id', async (req, res) => {
const key = `user:${req.params.id}`;
try {
const user = await cache(key, 300, async () => {
return await User.findById(req.params.id).lean();
});
res.json(user);
} catch (err) {
res.status(500).json({ error: err.message });
}
});Quản lý invalidation
Khi dữ liệu thay đổi, xóa cache tương ứng để tránh trả dữ liệu cũ.
app.put('/users/:id', async (req, res) => {
const { id } = req.params;
const updated = await User.findByIdAndUpdate(id, req.body, { new: true }).lean();
await client.del(`user:${id}`);
res.json(updated);
});Đánh giá hiệu năng
Thực hiện load test với autocannon:
npx autocannon -c 50 -d 30 http://localhost:3000/users/12345
Kết quả thường giảm thời gian phản hồi trung bình từ ~120ms (không cache) xuống 30‑40ms (có cache) và giảm tải DB đáng kể.
Kết luận
Redis cache giảm latency, tăng QPS, bảo vệ DB khỏi quá tải. Kết hợp với chiến lược TTL và invalidation, hệ thống giữ tính nhất quán.
Muốn học sâu hơn về kiến trúc Backend, Tham khảo khóa học "Lập trình Back-End với NodeJS Express" tại đây.




.png)



