How to Prevent Cache‑Database Consistency Issues in High‑Concurrency Systems
This article explains why cache‑database double‑write introduces consistency problems, introduces the Cache‑Aside pattern and lazy‑loading strategy, and proposes a queue‑based serialization approach to safely handle updates and reads in high‑concurrency backend systems.
Using a cache together with a database often leads to double‑write scenarios, which inevitably cause data‑consistency problems. If strict consistency is required, serializing read and write operations can guarantee correctness but dramatically reduces throughput.
Cache Aside Pattern
The classic approach is the Cache‑Aside pattern: on a read, first check the cache; if it misses, read from the database, populate the cache, and return the result. On an update, modify the database first and then delete the corresponding cache entry.
Deleting the cache instead of updating it is a form of lazy computation: the cached value may be derived from multiple tables or expensive calculations, so it is recomputed only when needed.
Basic Inconsistency Problem and Solution
If the cache is deleted after the database update and the delete fails, the cache holds stale data while the database has the new value. The simple fix is to delete the cache *before* updating the database; if the database update fails, the cache remains empty, and subsequent reads will fetch the old data from the database and repopulate the cache.
Complex Inconsistency Analysis
In high‑traffic environments, a race can occur: a process deletes the cache, begins a database update, and before the update finishes a read request finds the cache empty, reads the old database value, and writes it back to the cache. When the pending update finally commits, the cache now contains outdated data.
Proposed Queue‑Based Solution
Route all update and read‑‑‑cache‑miss operations through an internal JVM queue keyed by the data’s unique identifier. Each queue is serviced by a single worker thread that processes operations sequentially, ensuring that a cache‑delete followed by a DB update completes before any read can repopulate the cache.
Duplicate cache‑update requests can be filtered: if a pending update already exists in the queue, subsequent requests wait for the first one to finish.
Considerations for High Concurrency
1. Read request blocking : reads become asynchronous; they must respect timeout limits to avoid long‑lasting hangs.
2. Read request volume : extensive load testing is needed to verify that the system can handle spikes without overwhelming the queue.
3. Routing to the same service instance : updates and cache‑updates must be routed to the same instance (e.g., via Nginx hash routing) to keep ordering guarantees.
4. Hot‑item skew : popular items may concentrate load on a single queue; scaling out with multiple queues or instances can mitigate this.
By carefully sizing the number of queues, monitoring queue back‑log, and performing realistic performance tests, the solution can maintain consistency while supporting high read‑write concurrency.
Signed-in readers can open the original source through BestHub's protected redirect.
This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactand we will review it promptly.
21CTO
21CTO (21CTO.com) offers developers community, training, and services, making it your go‑to learning and service platform.
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.
