skills:cache
Differences
This shows you the differences between two versions of the page.
| Both sides previous revisionPrevious revisionNext revision | Previous revision | ||
| skills:cache [2026/05/26 06:56] – phong2018 | skills:cache [2026/05/26 06:58] (current) – [Sequence Diagram] phong2018 | ||
|---|---|---|---|
| Line 1: | Line 1: | ||
| - | Cache Invalidation Patterns in Real Production Systems | + | ====== |
| ===== Overview ===== | ===== Overview ===== | ||
| Line 7: | Line 7: | ||
| In real production systems, the hardest problem is: | In real production systems, the hardest problem is: | ||
| - | Keeping cache correct under concurrency and distributed timing | + | Handling |
| - | Most systems use hybrid strategies, not a single | + | Most systems use a combination of patterns, not a single |
| - | 1. Cache-Aside (Most Common Pattern) | + | ===== 1. Cache-Aside (Most Common Pattern) |
| - | ===== Concept | + | ==== Concept ==== |
| - | Application manages cache manually. Cache is disposable; | + | Application manages cache manually. Cache is a read-through optimization layer, |
| - | ===== Read Flow ===== | + | ==== Read Flow ==== |
| < | < | ||
| - | ===== Write Flow ===== | + | ==== Write Flow ==== |
| < | < | ||
| - | ===== Where it is used ===== | + | ==== Where it is used ==== |
| - | E-commerce | + | Microservices systems |
| - | Microservices APIs | + | E-commerce |
| - | Social | + | Social |
| - | ===== Pros ===== | + | ==== Pros ==== |
| Simple | Simple | ||
| Safe | Safe | ||
| Easy to debug | Easy to debug | ||
| + | Flexible | ||
| - | ===== Cons ===== | + | ==== Cons ==== |
| - | First read after miss is slow | + | Cache miss causes DB hit |
| Small stale window possible | Small stale window possible | ||
| - | 2. Write-Through Cache | ||
| - | ===== Concept | + | ===== 2. Write-Through Cache ===== |
| + | |||
| + | ==== Concept | ||
| Write goes through cache first, then DB. | Write goes through cache first, then DB. | ||
| - | ===== Flow ===== | + | ==== Flow ==== |
| < | < | ||
| - | ===== Pros ===== | + | ==== Pros ==== |
| Strong consistency | Strong consistency | ||
| No stale cache | No stale cache | ||
| - | ===== Cons ===== | + | ==== Cons ==== |
| Slower writes | Slower writes | ||
| Higher cost | Higher cost | ||
| - | 3. Write-Behind Cache | ||
| - | ===== Concept | + | ===== 3. Write-Behind Cache ===== |
| + | |||
| + | ==== Concept | ||
| Write goes to cache first, DB updated asynchronously. | Write goes to cache first, DB updated asynchronously. | ||
| - | ===== Flow ===== | + | ==== Flow ==== |
| < | < | ||
| - | ===== Pros ===== | + | ==== Pros ==== |
| Very fast writes | Very fast writes | ||
| High throughput | High throughput | ||
| - | ===== Cons ===== | + | ==== Cons ==== |
| Risk of data loss | Risk of data loss | ||
| Complex recovery | Complex recovery | ||
| - | 4. TTL-Based Invalidation | ||
| - | ===== Concept | + | ===== 4. TTL-Based Invalidation |
| + | |||
| + | ==== Concept | ||
| Cache expires automatically after time. | Cache expires automatically after time. | ||
| - | ===== Example | + | ==== Example ==== |
| < | < | ||
| - | ===== Pros ===== | + | ==== Pros ==== |
| Simple | Simple | ||
| - | Safe fallback | + | Safe fallback |
| - | ===== Cons ===== | + | ==== Cons ==== |
| - | Stale data until expiry | + | Stale data until expiration |
| - | 5. Event-Driven Invalidation | + | |
| - | ===== Concept | + | ===== 5. Event-Driven Invalidation |
| + | |||
| + | ==== Concept | ||
| - | DB changes | + | Database |
| - | ===== Flow ===== | + | ==== Flow ==== |
| < | < | ||
| - | ===== Pros ===== | + | ==== Pros ==== |
| - | Decoupled | + | Decoupled |
| - | Scales well | + | Scalable |
| - | ===== Cons ===== | + | ==== Cons ==== |
| Eventual consistency | Eventual consistency | ||
| Event delay or loss possible | Event delay or loss possible | ||
| - | 6. Critical Concept: | + | |
| - | 🟥 6.1 Update-on-write (RISKY | + | ===== 6. Update-on-write vs Invalidate-on-write |
| + | |||
| + | ==== 🟥 6.1 Update-on-write (RISKY | ||
| ===== Problem ===== | ===== Problem ===== | ||
| - | When multiple requests update same data concurrently, | + | Concurrent updates |
| ===== Scenario ===== | ===== Scenario ===== | ||
| Line 128: | Line 135: | ||
| Request B updates value = " | Request B updates value = " | ||
| - | ===== Sequence Diagram ===== | ||
| - | |||
| - | < | ||
| - | |||
| - | Client B Go API DB Redis | ||
| - | | | | | | ||
| - | |---update B--->| | | | ||
| - | | |---UPDATE---> | ||
| - | | |< | ||
| - | | |---SET B-------------------> | ||
| - | </ | ||
| ===== Problem ===== | ===== Problem ===== | ||
| - | If timing | + | If execution order is mixed: |
| - | DB: A → B (correct) | + | DB = B |
| - | Redis: A overwrites B (wrong) | + | Cache = A ❌ |
| - | + | ||
| - | Result: | + | |
| - | + | ||
| - | DB = "B" (correct) | + | |
| - | Cache = "A" (stale | + | |
| ===== Conclusion ===== | ===== Conclusion ===== | ||
| - | Update-on-write is unsafe | + | Update-on-write is unsafe |
| - | Race condition | + | Race conditions |
| Out-of-order execution | Out-of-order execution | ||
| - | Distributed timing | + | Distributed timing |
| - | 🟩 6.2 Invalidate-on-write (SAFE approach) | + | |
| + | ==== 🟩 6.2 Invalidate-on-write (SAFE pattern) ==== | ||
| ===== Concept ===== | ===== Concept ===== | ||
| Line 165: | Line 157: | ||
| Do NOT update cache. Only delete it. | Do NOT update cache. Only delete it. | ||
| - | ===== Sequence Diagram ===== | ||
| - | |||
| - | < | ||
| - | |||
| - | Client B Go API DB Redis | ||
| - | | | | | | ||
| - | |---update B--->| | | | ||
| - | | |---UPDATE---> | ||
| - | | |< | ||
| - | | |---DEL cache---------------> | ||
| - | </ | ||
| ===== Why it is safe ===== | ===== Why it is safe ===== | ||
| - | Even if requests are out of order: | + | Only DELETE operations on cache |
| - | + | No stale value can be written | |
| - | Cache only gets deleted multiple times | + | |
| - | No stale value is written | + | |
| ===== Read Flow ===== | ===== Read Flow ===== | ||
| - | < | + | < |
| Always consistent with DB. | Always consistent with DB. | ||
| - | 7. Comparison Table | + | ===== 7. Comparison Table ===== |
| - | Aspect Update-on-write Invalidate-on-write | + | |
| - | Cache operation SET DELETE | + | ^ Aspect |
| - | Race condition risk ❌ High ✅ Low | + | | Cache operation |
| - | Out-of-order | + | | Race condition risk | ❌ High | ✅ Low | |
| - | Debug complexity Hard Easy | + | | Out-of-order |
| - | Consistency Fragile Reliable | + | | Cache correctness | ❌ Fragile | ✅ Reliable | |
| - | 8. Key Insight | + | | Debug complexity |
| + | |||
| + | ===== 8. Key Insight | ||
| Cache is not the source of truth. | Cache is not the source of truth. | ||
| - | DB = truth | + | DB = source of truth |
| Cache = disposable optimization layer | Cache = disposable optimization layer | ||
| Invalidate-on-write works because: | Invalidate-on-write works because: | ||
| - | “Even if cache is wrong, it gets deleted anyway” | + | Even if cache is wrong, it will be deleted anyway. |
| - | 9. Production Pattern | + | ===== 9. Production Pattern |
| - | Most real systems use: | + | Most systems use: |
| - | < | + | < |
| READ: | READ: | ||
| Line 219: | Line 200: | ||
| </ | </ | ||
| - | 10. Why update-on-write still exists | + | ===== 10. Why Update-on-write still exists |
| - | Used only when: | + | Used only in limited cases: |
| - | Simple data (low concurrency) | + | Simple data |
| - | Need ultra-fast read-after-write | + | Low concurrency |
| - | No complex cache relationships | + | Ultra-fast read-after-write |
| Examples: | Examples: | ||
| Line 232: | Line 213: | ||
| Feature flags | Feature flags | ||
| Simple counters | Simple counters | ||
| + | |||
| + | ===== 11. Bonus Topics ===== | ||
| + | |||
| + | Cache stampede problem | ||
| + | Mutex / singleflight | ||
| + | Request coalescing | ||
| + | Kafka-based cache invalidation | ||
| + | Outbox pattern for reliability | ||
skills/cache.1779778599.txt.gz · Last modified: by phong2018
