Lesson 9 / 25
Caching Strategies
Hit ratios and invalidation.
Cache-aside, TTLs and eviction
With cache-aside, the application reads from the cache, falls back to the database on a miss and stores the result with a TTL; on writes it updates the database and deletes or updates the cache entry. Write-through writes to both synchronously; write-back writes to the cache and flushes later (fast but riskier). Eviction policies such as LRU keep popular items. Real workloads are skewed, so a small cache can absorb a large share of reads. Watch for stampedes on popular keys and stale data.
LRU hit ratio on a skewed workload, run
I ran this with Python 3.12.3 using only the standard library; inputs are fixed or seeded, so the output is reproducible. With 200,000 requests following a Zipf-like popularity, caching just 1% of items serves about half of all reads, and 20% serves about 78%.
# LRU cache hit ratio on a skewed (Zipf-like) workload
import random
from collections import OrderedDict
class LRU:
def __init__(self, capacity):
self.cap, self.data = capacity, OrderedDict()
self.hits = self.misses = 0
def get(self, key, load):
if key in self.data:
self.data.move_to_end(key); self.hits += 1
return self.data[key]
self.misses += 1
value = self.data[key] = load(key)
if len(self.data) > self.cap:
self.data.popitem(last=False) # evict least recently used
return value
rng = random.Random(7)
items = 100_000
weights = [1 / (i + 1) for i in range(items)] # item 0 is most popular
requests = rng.choices(range(items), weights=weights, k=200_000)
for cap in (1_000, 5_000, 20_000):
c = LRU(cap)
for key in requests:
c.get(key, lambda k: f"row {k}")
print(f"cache {cap:>6,} items ({cap / items:4.0%} of data): hit ratio {c.hits / len(requests):.1%}")
Output:
cache 1,000 items ( 1% of data): hit ratio 50.6% cache 5,000 items ( 5% of data): hit ratio 66.1% cache 20,000 items ( 20% of data): hit ratio 78.3%
Say how you invalidate
Interviewers often ask how cached data stays fresh; have an answer (TTL plus delete on write, or events).
Quick check: In cache-aside, what happens on a cache miss?
- The cache queries the database by itself and blocks writes
- The request fails
- The app reads from the database and stores the result in the cache
- The database is bypassed
Answer
The app reads from the database and stores the result in the cache — The application manages the cache.