Part 10 · System Design · 10.1.06

Cache placement, invalidation và hot keys

Cache đổi latency/load lấy staleness, memory và failure modes mới; khi thiết kế phải nói rõ source of truth nằm ở đâu và miss path sẽ đi qua những thành phần nào.

Mental model: cache không tạo dữ liệu đúng hơn. Nó giữ một bản sao để đọc nhanh hơn hoặc giảm tải. Vì vậy mọi quyết định cache phải trả lời ba câu hỏi: key là gì, dữ liệu cũ được chấp nhận bao lâu, và chuyện gì xảy ra khi cache miss/down.

1. Cache layers

Browser/CDN phù hợp với public/static content; reverse proxy có thể cache HTTP response; distributed cache chia sẻ dữ liệu giữa nhiều application instance; in-process cache nhanh nhất nhưng chỉ sống trong từng instance và khó invalidate đồng bộ. Cache key phải bao gồm tenant, auth, locale, version hoặc bất kỳ dimension nào làm response thay đổi.

LayerĐiểm mạnhRủi ro / trade-off cần nói
Browser cacheGần user nhất, giảm network requestKhó thu hồi ngay dữ liệu đã phát hành; policy HTTP phải đúng.
CDNGiảm latency theo vùng và origin bandwidthPhải phân biệt public/private response, purge/versioning và regional miss.
Reverse proxyCache HTTP response trước applicationKey phải phản ánh header/query/identity thật sự ảnh hưởng representation.
Distributed cacheNhiều app instance cùng dùng một cacheThêm network hop, cluster failure mode, eviction và hot key.
In-process cacheKhông network hop, latency rất thấpMỗi instance có bản sao riêng; invalidation và consistency khó hơn.
Cache key là một phần của correctness. Nếu response khác nhau theo tenant, quyền truy cập, locale hay version mà key bỏ qua dimension đó, cache có thể trả dữ liệu sai hoặc làm lộ dữ liệu giữa các user/tenant.

2. Cache patterns và invalidation

Cache-aside là pattern phổ biến: application đọc cache trước, miss thì đọc source of truth rồi populate cache. Read-through, write-throughwrite-behind phụ thuộc semantics mà provider thực sự cung cấp; không nên suy diễn rằng mọi cache product đều có cùng guarantee.

TTL giới hạn thời gian một entry có thể tồn tại nhưng không bảo đảm dữ liệu luôn fresh. Với dữ liệu thay đổi, invalidate hoặc update cache nên xảy ra sau khi transaction ở source of truth commit. Việc dual write vào cache và database không tự động atomic, vì vậy có thể xảy ra trạng thái một bên thành công còn bên kia thất bại.

PatternRead pathWrite path / semantics cần chú ý
Cache-asideApp → cache; miss → DB → cacheApplication tự chịu trách nhiệm populate/invalidate; dễ hiểu nhưng có stale window.
Read-throughApp đọc qua cache providerProvider thực hiện load; behavior khi load fail phải kiểm tra theo implementation.
Write-throughRead từ cacheWrite đi qua cache tới backing store; latency và atomic boundary là provider-specific.
Write-behindRead từ cacheCache flush về backing store sau; giảm write latency nhưng tăng risk khi cache fail trước khi persist.
TTL ≠ freshness guarantee. TTL chỉ đặt upper bound cho vòng đời entry nếu entry không bị refresh/invalidate theo cơ chế khác. Requirement cần nói rõ có chấp nhận stale data không và tối đa bao lâu.

3. Cache stampede và hot key

Khi một entry phổ biến hết hạn hoặc bị evict, nhiều request đồng thời có thể cùng miss và cùng đánh source of truth. Các kỹ thuật thường dùng là single-flight/request coalescing, jittered TTL, stale-while-revalidate, early refreshadmission control.

Hot key là một key nhận lượng truy cập lớn bất thường. Có thể giảm áp lực bằng cách replicate dữ liệu, thêm local cache, hoặc shard phần work có thể tách. Scale-out cache cluster không tự động chia tải cho một key duy nhất nếu tất cả request vẫn map tới cùng owner/partition.

3.1 Stampede: vì sao nguy hiểm?

3.2 Mitigation matrix

Kỹ thuậtÝ nghĩaTrade-off
Single-flight / request coalescingMột request refresh; các request khác chờ hoặc dùng kết quả chungCần timeout/bounded wait để tránh một loader chậm giữ mọi request.
Jittered TTLThêm ngẫu nhiên vào TTL để entry không cùng hết hạnKhông loại bỏ miss; chỉ làm phẳng burst.
Stale-while-revalidateCho phép trả stale trong khi background/one request refreshPhải có staleness budget rõ ràng.
Early refreshRefresh trước khi TTL hết khi entry đủ hotTăng refresh traffic, cần policy để không refresh mọi key.
Admission controlGiới hạn request được phép đi tiếp xuống miss pathCó thể reject/degrade một phần traffic để bảo vệ dependency.

4. Failure behavior

Cache down có thể tạo thundering herd vào database nếu toàn bộ request chuyển thẳng sang source of truth. Thiết kế cần có circuit, concurrency limit và degraded response phù hợp để bảo vệ dependency quan trọng hơn.

Negative caching giúp giảm repeated miss cho dữ liệu không tồn tại, nhưng TTL nên ngắn để không che dữ liệu vừa được tạo sau đó. Eviction policy phải xét working set của workload; một cache đầy không có nghĩa hit ratio sẽ tốt nếu policy liên tục đẩy các key hữu ích ra ngoài.

Sự cốFailure modePhản ứng mong muốn
Cache unavailableMọi read trở thành miss, DB/downstream bị burstCircuit, bounded concurrency, rate limit hoặc degraded response.
Cache latency tăngCache trở thành bottleneck thay vì optimizationTimeout ngắn, fallback có kiểm soát; không cho request treo vô hạn.
Negative cache quá lâuChe item vừa được tạoTTL ngắn và invalidate khi create nếu workflow cần thấy ngay.
Eviction churnHit ratio giảm, dependency load tăngĐo working set/hit ratio/eviction; điều chỉnh capacity hoặc admission/policy.
Fallback không được biến thành outage lớn hơn. “Nếu cache lỗi thì đọc DB” chỉ an toàn khi DB đã được capacity cho miss storm hoặc khi application có giới hạn concurrency/rate để bảo vệ DB.

5. CDN

CDN sử dụng HTTP caching primitives như Cache-Control và validators như ETag. Thiết kế production cần xét origin shield, purge hoặc versioned URL, signed URL/cookie và hiện tượng regional miss. Personalized/private response không được cache public theo cách làm rò rỉ representation của user này sang user khác.

CDN giảm latency đọc và origin bandwidth cho content cacheable, nhưng không sửa write path: write vẫn phải đi về hệ thống sở hữu dữ liệu, xử lý consistency và invalidation theo thiết kế riêng.

5.1 Purge hay versioned URL?

5.2 Public vs private

Security rule: dữ liệu cá nhân hóa hoặc phụ thuộc authorization cần policy rõ ràng trước khi cache ở shared/public layer. Khi representation thay đổi theo identity, cache key/policy phải phản ánh điều đó hoặc không cache ở shared CDN.

6. Review checklist

Tài liệu chính thức từ source BK: RFC 9111 · HTTP Caching · Microsoft Azure · Cache-Aside Pattern