Đi đến nội dung chính
VI
Trang chủ / Bài viết / Cache ba tầng an toàn cho SaaS nhiều khách hàng
15 thg 1, 2026 · Z-SOFT Admin · 10 phút đọc

Cache ba tầng an toàn cho SaaS nhiều khách hàng

Cách kết hợp trình duyệt, CDN và Redis để tăng tốc hệ thống mà vẫn giữ dữ liệu của từng khách hàng tách biệt.

Xem tất cả bài viết

Ý chính: Dữ liệu công khai có thể được lưu gần người dùng. Dữ liệu riêng phải luôn gắn với đúng khách hàng và có quy tắc làm mới rõ ràng.

Thuật ngữ trong bài: Tenant: một khách hàng dùng nền tảng; cache: bản sao dữ liệu để đọc nhanh; invalidation: làm cho bản cache cũ hết hiệu lực.

Bài toán thực tế

Thêm Redis chưa đủ để có một hệ thống cache an toàn. Khi một khóa hết hạn, hàng loạt yêu cầu có thể cùng truy vấn cơ sở dữ liệu. Nếu cấu hình cache sai, dữ liệu của khách hàng này còn có thể xuất hiện trong phản hồi dành cho khách hàng khác.

Điểm dễ bị bỏ qua

Cache không chỉ là một tối ưu hiệu năng; đó là một bản sao của dữ liệu được đặt ở nơi khác. Trước khi thêm một tầng cache, đội ngũ phải trả lời rõ bản sao này thuộc khách hàng nào, được phép cũ trong bao lâu và được làm mới bằng cơ chế nào.

Trong SaaS nhiều khách hàng, một phản hồi nhanh nhưng sai ranh giới dữ liệu là lỗi nghiêm trọng hơn nhiều so với một phản hồi chậm. Vì vậy, khóa cache và quy tắc CDN phải được kiểm thử với ít nhất hai khách hàng ngay từ đầu.

Luồng xử lý

Trình duyệt
Cache phản hồi cục bộ
CDN
Chỉ dữ liệu công khai
Redis
Cache dùng chung của ứng dụng
Cơ sở dữ liệu
Nguồn dữ liệu chuẩn
Mỗi tầng bớt đi một phần việc lặp lại, nhưng khóa cache riêng vẫn phải chứa định danh khách hàng.

Thiết kế và triển khai

Tách luồng công khai và luồng riêng tư

Chỉ đưa lên CDN dùng chung những phản hồi ẩn danh và giống hệt nhau với mọi người dùng.

Ngăn hiện tượng nhiều yêu cầu cùng dựng lại cache (nhiều yêu cầu cùng lúc dựng lại một khóa vừa hết hạn)

Khi một khóa bị truy cập dồn dập hết hạn, hãy bảo vệ việc dựng lại bằng khóa phân tán ngắn hoặc single-flight.

Ưu tiên việc làm mới cache theo phiên bản

Xóa mọi khóa liên quan rất dễ bỏ sót.

Đi sâu vào thiết kế

Tính nhất quán là một quyết định sản phẩm

TTL không chỉ là một tham số hạ tầng. Người phụ trách sản phẩm phải quyết định trường dữ liệu nào được phép cũ, và cũ trong bao lâu.

Kiểm soát khóa bị truy cập dồn dập và số lượng biến thể cache

Việc gắn dữ liệu theo khách hàng có thể phình lên hàng triệu khóa, nếu bộ lọc, phân trang và ngôn ngữ bị đưa vào một cách tùy tiện. Hãy chuẩn hóa tham số truy vấn, chỉ băm những chiều đã được cho phép, và giới hạn số biến thể có thể cache.

Cách triển khai

  1. Phân loại phản hồi là công khai hay riêng tư trước khi quyết định tầng nào được phép cache.
  2. Dùng single-flight để khi một khóa hết hạn chỉ có một yêu cầu dựng lại dữ liệu, các yêu cầu còn lại chờ hoặc nhận bản cũ trong giới hạn cho phép.
  3. Đưa mã khách hàng và phiên bản dữ liệu vào khóa cache; tăng phiên bản mỗi khi dữ liệu liên quan thay đổi.

Mã minh họa: Đọc cache theo khách hàng với stale-while-revalidate

key = `catalog:${tenantId}:v${catalogVersion}:${queryHash}`
cached = await redis.get(key)
if (cached && cached.age < freshFor) return cached.value

lock = await redis.set(`${key}:lock`, requestId, { NX: true, PX: 3000 })
if (!lock && cached && cached.age < staleFor) return cached.value

value = await db.catalog.findMany({ where: { tenantId } })
await redis.set(key, encode(value), { EX: staleFor })
return value

Nếu dùng khóa để chống dựng lại đồng thời, mỗi lần giữ khóa cần có mã chủ sở hữu và chỉ chính chủ mới được nhả khóa.

Rủi ro cần tính trước

  • Thiếu mã khách hàng tạo ra một khóa dùng chung cho toàn hệ thống.
  • Giao dịch cơ sở dữ liệu đã hoàn tất nhưng bước làm mới cache thất bại.
  • Redis ngừng hoạt động và toàn bộ lưu lượng bất ngờ dồn xuống cơ sở dữ liệu.

Nên theo dõi gì?

Tín hiệuĐiều tín hiệu cho biết
Tỷ lệ đọc trúng cache theo endpoint và khách hàngPhát hiện endpoint không phù hợp để cache hoặc một khách hàng đang tạo tải bất thường.
Số lần dựng lại và thời gian chờ khóaTăng đột biến thường cho thấy nhiều yêu cầu đang cùng dựng lại một khóa vừa hết hạn.
Số truy vấn cơ sở dữ liệu trên mỗi yêu cầuXác nhận cache thật sự loại bỏ công việc phía sau thay vì chỉ chuyển chi phí sang nơi khác.
Số phản hồi dùng dữ liệu cũ và độ trễ làm mớiĐo cái giá về tính nhất quán đang được đánh đổi để lấy tốc độ đọc.

Cách kiểm chứng

  • Gửi cùng một yêu cầu đồng thời cho hai khách hàng, và chứng minh phản hồi nội dung, ETag cùng khóa cache không bao giờ bị dùng chéo.
  • Cho một khóa bị truy cập dồn dập hết hạn dưới tải, rồi xác nhận số lần dựng lại cơ sở dữ liệu chỉ bằng một, hoặc bằng đúng giá trị bạn đã đặt giới hạn.
  • Commit một thay đổi trong khi tiến trình làm mới cache đang dừng, sau đó bật lại và kiểm tra rằng phiên bản mới cuối cùng cũng hiển thị.
  • Tắt Redis rồi đo xem giới hạn mức xử lý đồng thời của cơ sở dữ liệu có giữ được luồng dự phòng trong mục tiêu độ trễ hay không.
  • Kiểm thử phản hồi công khai qua một cấu hình CDN thật, gồm cả hành vi của Vary, Cookie và phân quyền.

Đưa vào production từng bước

Nên bắt đầu với một endpoint đọc nhiều nhưng ít rủi ro. Chạy cache ở chế độ đối chiếu, theo dõi tỷ lệ đọc trúng, độ cũ của dữ liệu, độ trễ Redis và số truy vấn cơ sở dữ liệu; chỉ trả dữ liệu từ cache khi kết quả đã ổn định.

Checklist trước khi vận hành

  • Đọc nhanh hơn luôn đi kèm một khoảng thời gian dữ liệu có thể là cũ (dữ liệu cũ nhưng vẫn dùng tạm).
  • Kiểm thử header và khóa cache với ít nhất hai khách hàng, đừng chỉ chạy một luồng thuận lợi.
  • Theo dõi cùng lúc tỷ lệ lần đọc trúng cache, số lần tạo lại cache và số truy vấn cơ sở dữ liệu.

Điều cần nhớ

Cache tốt không chỉ làm hệ thống nhanh hơn. Nó còn cho phép đội ngũ nhìn rõ dữ liệu thuộc về ai, có hiệu lực bao lâu và được làm mới khi nào.

HỢP TÁC CÙNG Z-SOFT

Mỗi quyết định công nghệ hôm nay đều ảnh hưởng đến nhiều năm sau.

Trao đổi với đội ngũ Z-SOFT để đánh giá hiện trạng, xác định mục tiêu và lựa chọn kiến trúc phù hợp với định hướng phát triển của doanh nghiệp.

Đặt lịch tư vấn