Day 31: Cache Eviction and Consistency – The Architect’s Sword Against Stale Data
Welcome back, architects and engineers, to another deep dive into the practicalities of building hyperscale systems. Today, we confront a silent killer of user experience and system integrity: stale data in the cache.
You've heard me say it before, and it bears repeating: A stale cache is worse than no cache. Why? Because an empty cache simply means a slightly slower request, hitting the primary data store. But a stale cache? That means your users are seeing incorrect information, making decisions based on outdated facts. Imagine an e-commerce platform showing an item "in stock" when it's already sold out, or a financial dashboard displaying old portfolio values. This isn't just an inconvenience; it's a breach of trust and a potential operational nightmare.
Today, we're not just understanding the problem; we're arming ourselves with a critical tool: Cache Eviction, specifically using Spring Boot's @CacheEvict annotation. This isn't just about adding an annotation; it's about understanding the control flow, data flow, and state changes that occur when data shifts in a distributed system.
The Problem: When Reality Diverges from Cache
In our journey to handle 100 million requests per second, we introduced caching (Day 29) to offload our primary database and reduce latency. We used @Cacheable to store frequently accessed data. Great! Reads are fast.
But what happens when the underlying data changes? If our InventoryService updates an item's stock count in the database, but the cache still holds the old value, any subsequent read requests will return the incorrect, cached data. This divergence between the source of truth (the database) and our high-speed replica (the cache) is the consistency problem in action.
The Solution: @CacheEvict β Forcing a Refresh
The simplest and most common strategy to maintain cache consistency with write-through/write-back caches is cache invalidation or eviction. When a piece of data is modified in the primary data store, we proactively remove (evict) its corresponding entry from the cache. This forces the next read request for that data to go to the primary data store, fetch the fresh value, and then (if @Cacheable is present) re-cache it.
Think of it like this: You have a whiteboard (your cache) where you jot down quick notes (data). When the official document (your database) changes, you don't try to manually update your whiteboard note. You just erase it. The next time you need that information, you'll look at the official document and write the new, correct information on your whiteboard.
Core Concepts: Control Flow, Data Flow, and State Changes
Let's break down how this works in our InventoryService:
Keep going with the full lesson
The rest of this lesson β plus its implementation guide, runnable scripts and source code β is included with the course or an All Access plan. Create a free account to start the free lessons in every course.
Already a member? Sign in