Redis cache và queue: tăng tốc backend mà không làm sai dữ liệu
Backend

Redis cache và queue: tăng tốc backend mà không làm sai dữ liệu

Nam Nguyen
3 phút đọc
4 lượt xem
#redis
#cache
#queue
#backend

Redis nhanh nhưng không phải thuốc chữa mọi bệnh#

Redis thường được dùng để cache, rate limit, session, lock nhẹ và queue. Nó giúp giảm tải database và tăng tốc response, nhưng cũng có thể tạo bug khó debug nếu cache sai key, TTL quá dài, dữ liệu stale, job chạy trùng hoặc lock không có timeout. Dùng Redis tốt cần hiểu trade-off giữa tốc độ, độ đúng và độ phức tạp vận hành.

Cache-aside là pattern dễ bắt đầu#

Với cache-aside, application đọc cache trước. Nếu miss, app đọc database, ghi cache rồi trả response. Pattern này đơn giản, nhưng cần key rõ ràng, TTL hợp lý và invalidation khi dữ liệu thay đổi.

TypeScript
async function getPost(slug: string) {
  const key = `post:${slug}`;
  const cached = await redis.get(key);
  if (cached) return JSON.parse(cached);

  const post = await db.posts.findBySlug(slug);
  if (!post) return null;

  await redis.set(key, JSON.stringify(post), { EX: 300 });
  return post;
}

Không nên cache response chứa dữ liệu cá nhân bằng key quá chung. Ví dụ dashboard:stats có thể lộ dữ liệu giữa user nếu key không chứa tenant hoặc user id phù hợp.

TTL, invalidation và cache stampede#

TTL quá ngắn làm cache ít tác dụng; TTL quá dài làm user thấy dữ liệu cũ. Với dữ liệu thay đổi theo event như bài viết, hãy xóa key khi publish/edit. Với dữ liệu tổng hợp tốn kém, có thể dùng TTL kèm stale-while-revalidate hoặc background refresh.

Cache stampede xảy ra khi một key nóng hết hạn và nhiều request cùng lúc đổ vào database. Có thể giảm bằng lock ngắn, jitter TTL, request coalescing hoặc phục vụ dữ liệu stale trong lúc refresh.

Queue cần idempotency#

Redis-backed queue rất hữu ích cho gửi email, resize ảnh, gọi webhook, tạo report hoặc sync dữ liệu. Nhưng job có thể chạy lại vì worker restart, timeout, network lỗi hoặc retry. Vì vậy job phải idempotent: chạy nhiều lần vẫn không tạo side effect sai.

  • Dùng idempotency key cho thao tác gửi webhook hoặc tạo thanh toán.
  • Lưu trạng thái job quan trọng trong database, không chỉ trong memory.
  • Đặt retry có giới hạn và đưa job lỗi vào dead-letter queue.
  • Log job id, attempt, duration và lỗi cuối cùng.

Rate limit với Redis#

Redis phù hợp rate limit vì thao tác tăng bộ đếm rất nhanh và có TTL. Endpoint login, comment, contact, search và upload nên có giới hạn riêng. Với hệ thống nhiều instance, rate limit trong memory từng server không đủ nhất quán; Redis hoặc service gateway sẽ đáng tin hơn.

Text
key: rate:contact:ip:203.0.113.10
value: 4
ttl: 600 seconds

Khi nào không nên dùng Redis?#

Đừng dùng Redis để che query database chưa có index. Trước tiên hãy đo bằng query plan, thêm index đúng và tối ưu schema. Đừng dùng Redis làm source of truth cho dữ liệu cần bền vững nếu bạn chưa cấu hình persistence, backup và recovery. Đừng đưa toàn bộ domain logic vào cache layer khiến hệ thống khó hiểu.

Checklist Redis production#

  • Key naming có namespace, tenant/user scope khi cần.
  • TTL có jitter cho key nóng để giảm stampede.
  • Invalidation chạy ở luồng ghi dữ liệu quan trọng.
  • Không cache dữ liệu nhạy cảm nếu không có kiểm soát scope và mã hóa phù hợp.
  • Queue job có idempotency, retry limit và dead-letter queue.
  • Monitoring có memory usage, hit rate, evictions, latency và connected clients.
  • Redis được bảo vệ network, auth và backup nếu chứa dữ liệu quan trọng.

Nguồn tham khảo chính#

Chia sẻ bài viết

Giúp người khác tìm thấy bài viết này

Bình luận

Đang tải bình luận...

Đang tải bình luận...

Để lại bình luận

Email của bạn sẽ không được công khai

Tối thiểu 10 ký tự

0 / 5000