Khi bắt đầu triển khai cache vào hệ thống thực tế, một câu hỏi mới xuất hiện:

Nếu dữ liệu đã nằm trong cache, ứng dụng sẽ đọc và ghi dữ liệu như thế nào?

Nghe có vẻ đơn giản, nhưng đây chính là nơi xuất hiện hàng loạt chiến lược caching khác nhau.

Mỗi chiến lược đều cố gắng cân bằng giữa ba yếu tố:

  • Hiệu năng

  • Tính nhất quán dữ liệu

  • Độ phức tạp khi triển khai

Không có chiến lược nào tốt nhất cho mọi hệ thống. Điều quan trọng là hiểu cách chúng hoạt động để lựa chọn phù hợp với bài toán của mình.


Application Managed Cache

Đặc điểm:

  • Application chịu trách nhiệm quản lý việc đọc và ghi giữa Cache và Database.

  • Đây là mô hình phổ biến nhất trong các hệ thống hiện nay vì đơn giản và dễ triển khai.

Cache Aside + Cache Invalidation

Đây là cặp chiến lược thường được sử dụng cùng nhau.

Cache Aside

Khi cache hit:

  • Trả thẳng dữ liệu có từ cache

Khi cache miss:

  • Ứng dụng đọc từ Database

  • Đưa dữ liệu vào Cache

  • Trả kết quả về cho người dùng

Cache Invalidation

Khi nào cần ghi mới dữ liệu vào cache

  • Những thành phần phần cấu hình nên dữ liệu này đã được thay đổi

  • Khi phần dữ liệu được cache không còn do đã bị xoá hoặc đã hết hạn

Khi ghi đạt vào trong 2 điều kiện trên :

  • Cache không được cập nhật ngay.

  • Dữ liệu chỉ được đưa vào Cache khi có nhu cầu đọc sau đó.

Ví dụ

User cập nhật hồ sơ:

  1. Cập nhập profile customer ở disk database

  2. Xóa cache liên quan đến hồ sơ vừa được cập nhật

  3. Lần request profile tiếp theo phát hiện cache Miss

  4. Query dữ liệu từ disk và load lại vào cache.

Ưu điểm

  • Đơn giản, dễ triển khai ở bất kỳ đâu trong toàn bộ logic của dự án

  • Chỉ cache dữ liệu thực sự được sử dụng ở những chỗ cần thiết

  • Giảm dung lượng cache sử dụng vì chỉ những dữ liệu thực sự được truy cập mới được đưa vào cache.

Nhược điểm

  • Cache miss đầu tiên luôn phải truy cập Database

  • Read đầu tiên sau cache Miss sẽ take time nếu là api cần xử lý lâu

  • Dễ gặp Cache Stampede (Nhiều request cùng lúc gặp Cache Miss và đồng thời truy vấn Database)

  • Khó quản lý các luồng đọc/ghi cache khi triển khai rải rác khắp source

Phù hợp

  • Product Catalog

  • User Profile

  • CMS

  • Hầu hết hệ thống CRUD

  • Dữ liệu ghi nhiều nhưng không phải lúc nào cũng được đọc


Cache Layer Managed Cache

  • Cache Loader / Data Source Adapter sẽ được Cache layer được cấu hình trước.

  • Toàn bộ trách nhiệm đọc và ghi được giao cho Cache Layer.

  • Cách tiếp cận này thường xuất hiện trong các hệ thống lớn hoặc nền tảng có nhiều service dùng chung dữ liệu.

Luồng đọc (Read Through)

Khi cache miss:

  • Cache Layer tự động lấy dữ liệu từ Database

  • Tự cập nhật Cache

  • Trả kết quả cho Application

Application không cần biết dữ liệu đến từ đâu.

Luồng ghi (Write Through)

Khi ghi dữ liệu:

Application
    |
    v
 Cache Layer
    |
    +--> Cache
    |
    +--> Database

Sau khi ghi:

Cache = New Value
DB    = New Value

Ví dụ

Application cập nhật giá sản phẩm:

Update Product Price
         |
         v
      Cache Layer
         |
    +----+----+
    |         |
 Cache      Database

Kết quả:

Cache = 100$
DB    = 100$

Lần đọc tiếp theo:

Read Product Price
        |
        v
      Cache Hit

Ưu điểm

  • Logic cache được tập trung vào một chỗ

  • Application đơn giản hơn

  • Cache và Database được cập nhật trong cùng luồng ghi nên độ nhất quán rất cao.

  • Read sau Write thường là Cache Hit

  • Dễ quản lý khi có nhiều service

Nhược điểm

  • Cần Cache Provider hoặc Cache Loader

  • Triển khai phức tạp hơn

  • Mỗi lần ghi phải cập nhật cả Cache và Database, làm tăng độ trễ ghi và số lượng thao tác I/O.

Phù hợp

  • Hệ thống lớn

  • Microservices

  • Pricing Service

  • Product Information

  • Metadata Service

  • Nhiều service cùng truy cập dữ liệu


Tối ưu hiệu năng khi write

  • Hai nhóm phía trên tập trung vào tính nhất quán dữ liệu.

  • Một số hệ thống chấp nhận đánh đổi tính nhất quán để đổi lấy tốc độ ghi.

Write Behind (Write Back)

Ghi vào Cache trước, Database cập nhật sau.

Ưu điểm

  • Tốc độ ghi cực nhanh

  • Giảm tải Database

  • Hỗ trợ batch write hiệu quả

Nhược điểm

  • Eventual Consistency

  • Nguy cơ mất dữ liệu khi hệ thống gặp sự cố

  • Khó xử lý rollback

Phù hợp

  • Like Counter

  • View Counter

  • Analytics

  • Logging

  • Telemetry

Không phù hợp

  • Thanh toán

  • Số dư tài khoản

  • Giao dịch tài chính

  • Inventory thời gian thực


Định kỳ làm mới dữ liệu

Refresh Ahead : Làm sao giảm Cache Miss?

Thường chỉ áp dụng cho các dữ liệu được truy cập thường xuyên hoặc có giá trị cao.

Thông thường:

TTL = 10 phút

10:00 Cache Expired
10:01 User Request
10:01 Database Query

Người dùng đầu tiên sau khi cache hết hạn sẽ phải chờ Database.

Refresh Ahead chủ động làm mới dữ liệu trước khi cache hết hạn.

TTL còn 10%
      |
      v
Background Job
      |
      v
Refresh Cache

Kết quả:

  • Cache luôn nóng

  • Giảm Cache Miss

  • Latency ổn định hơn

Phù hợp

  • Homepage

  • Trending Products

  • Dashboard

  • Configuration Data

  • Frequently Accessed Data