Cache Consistency Issues and Solutions: Cache‑Aside Pattern, Lazy Deletion, and High‑Concurrency Queue Design
This article explains the fundamental cache‑aside pattern, why lazy cache deletion is preferred over immediate updates, analyzes simple and complex cache‑database inconsistency scenarios, and proposes a high‑concurrency queue‑based solution with practical considerations for backend systems.
Cache Aside Pattern
The classic cache‑plus‑database read/write model is the Cache Aside Pattern: on read, check the cache first, fall back to the database if missing, then populate the cache; on update, write to the database first and then delete the cache.
Why Delete the Cache Instead of Updating It?
In complex scenarios the cached value may be derived from multiple tables, making direct cache updates expensive; deleting the cache avoids costly recomputation until the data is actually needed, embodying a lazy‑calculation approach similar to lazy loading in ORM frameworks.
Basic Cache Inconsistency Problem and Solution
Problem: updating the database then deleting the cache can lead to inconsistency if cache deletion fails, leaving stale data in the cache.
Solution: delete the cache first, then update the database; if the database update fails, the cache remains empty, preventing stale reads.
Analysis of More Complex Inconsistency Scenarios
When a write deletes the cache, then a read occurs before the database update finishes, the read may fetch stale data from the database and repopulate the cache, causing divergence.
Why This Happens Under Billion‑Scale Traffic
High read‑write concurrency makes the window between cache deletion and database update vulnerable; with millions of requests per second, such inconsistencies become likely.
Solution: route all update operations for a given data item to a single JVM internal queue; reads that miss the cache also enqueue a cache‑refresh request, ensuring serialized execution.
The queue processes operations one by one: a delete‑cache request is followed by the database update, then a read‑refresh that repopulates the cache with the latest value.
If a read request arrives while the queue is busy, it can wait for the cache to be refreshed or fall back to reading the database after a timeout.
High‑Concurrency Considerations
1. Long‑running read blocking: ensure read timeouts are respected; excessive queue buildup can cause many reads to time out and hit the database directly.
2. Read request surge: perform load testing to verify the system can handle peak concurrent reads without excessive latency.
3. Multi‑instance routing: guarantee that updates and corresponding cache refreshes for the same key are routed to the same service instance (e.g., via Nginx hash routing).
4. Hot‑item skew: monitor and possibly shard hot keys across multiple queues or instances to avoid overloading a single node.
Final Note (Please Follow)
The author provides PDFs of three technical columns (Spring Cloud, Spring Boot, Mybatis) via a public WeChat account; readers are encouraged to like, share, and follow for more content.
Code Ape Tech Column
Former Ant Group P8 engineer, pure technologist, sharing full‑stack Java, job interview and career advice through a column. Site: java-family.cn
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.