Ensuring Data Consistency Between MySQL and Redis in High‑Concurrency Scenarios
This article analyzes why data inconsistencies arise when MySQL and Redis are used together under high load, compares cache‑delete ordering problems, and presents two practical solutions—delayed double‑delete and asynchronous binlog‑driven cache updates—along with implementation tips and trade‑offs.
In high‑concurrency environments, direct access to MySQL can cause performance bottlenecks, so Redis is commonly used as a cache layer. However, because MySQL and Redis are separate data stores, maintaining consistency between them becomes a critical challenge.
1. Causes of data inconsistency
Heavy concurrent reads make the database the weakest link.
Using Redis as a buffer reduces direct MySQL traffic, but cache reads are fine while cache writes introduce synchronization issues.
When updating data, both the database and the cache must be updated; otherwise stale (dirty) data may appear in Redis.
Typical workflow: read from Redis, if miss then read from MySQL and populate the cache.
2. Cache‑delete ordering problems
Whether the cache is deleted before or after the database write, inconsistency can occur.
2.1 Delete cache first
If the cache is removed before the MySQL write completes, another thread may read the empty cache, fall back to MySQL, and write stale data back to Redis.
The database update then makes Redis and MySQL diverge.
2.2 Delete cache after write
If the database write succeeds but the subsequent cache deletion fails (e.g., the thread crashes), subsequent reads will fetch the old cache value, causing inconsistency.
Concurrent reads and writes cannot guarantee order, leading to mismatched data.
3. Solutions
3.1 Delayed double‑delete strategy
Basic idea : delete the cache both before and after the database write, with a short sleep in between.
Pseudo‑code:
public void write(String key, Object data) {
redis.delKey(key);
db.updateData(data);
Thread.sleep(500);
redis.delKey(key);
}Steps:
Delete the cache.
Write to the database.
Sleep for a configurable period (e.g., 500 ms, adjusted based on the average read‑latency of the business).
Delete the cache again.
The sleep duration should be chosen based on the expected time for read operations to finish; adding a few hundred milliseconds (or up to a second) is typical.
3.2 Asynchronous cache update via MySQL binlog
Overall flow :
Capture data‑modifying events from MySQL binlog.
Publish these events to a message queue (e.g., Kafka, RabbitMQ).
Consumers read the queue and apply incremental updates to Redis.
This approach mirrors MySQL master‑slave replication: changes are recorded in the binlog, then propagated to Redis, ensuring eventual consistency without blocking reads.
4. Summary
In high‑concurrency scenarios with strict consistency requirements, identify the root causes of cache‑database divergence.
Two effective mitigation techniques are the delayed double‑delete strategy and asynchronous binlog‑driven cache updates.
Setting appropriate cache expiration times is also essential to guarantee eventual consistency.
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.
Architect
Professional architect sharing high‑quality architecture insights. Topics include high‑availability, high‑performance, high‑stability architectures, big data, machine learning, Java, system and distributed architecture, AI, and practical large‑scale architecture case studies. Open to ideas‑driven architects who enjoy sharing and learning.
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.
