How to Keep Redis Cache Consistent with Database: Strategies and Pitfalls
This article examines the consistency challenges when using Redis as a cache for database data, compares three update strategies, and presents practical solutions such as delayed double‑delete, retry mechanisms, and handling cache penetration, avalanche, and thread‑safety issues in Java.
Cache Consistency Problem
When using Redis as a high‑performance cache, updating data can lead to inconsistency between the cache and the underlying database.
Three Update Strategies
Update database then update cache.
Delete cache then update database.
Update database then delete cache.
Analysis shows the first strategy can cause dirty data due to race conditions, while the second can produce stale reads if the cache is deleted before the database write completes. The third strategy, also known as the Cache‑Aside pattern, is widely adopted but still has edge cases.
Delay Double‑Delete Solution
To mitigate the second strategy’s inconsistency, a delayed double‑delete is used: delete the key, write to the database, sleep for a short period (e.g., 1 s), then delete the key again.
public void write(String key, Object data) {
redis.delKey(key);
db.updateData(data);
Thread.sleep(1000);
redis.delKey(key);
}The sleep duration should be based on the expected read‑operation latency plus a safety margin.
Handling Cache‑Delete Failures
If the second delete fails, a retry mechanism is required. Two approaches are presented: (1) send the failed key to a message queue and retry until success; (2) subscribe to the MySQL binlog (e.g., using Canal) and perform asynchronous retries.
Other Cache Issues
Cache penetration – use placeholder values or Bloom filters.
Cache avalanche – stagger expiration times and use distributed locks.
Cache “no‑bottom‑hole” – avoid excessive mget calls by balancing node count.
HashMap Internals and Thread Safety
Since JDK 1.8, HashMap switches from linked‑list buckets to red‑black trees when a bucket exceeds eight entries, improving lookup performance. The structure is not thread‑safe; concurrent puts can lose entries or cause loops during resizing. Using synchronized wrappers or ConcurrentHashMap resolves these issues.
Common Java Thread Pools
newCachedThreadPool – unbounded thread creation with idle‑thread timeout.
newFixedThreadPool – fixed number of worker threads.
newSingleThreadExecutor – single worker guaranteeing task order.
newScheduledThreadPool – supports delayed and periodic tasks.
Understanding their parameters and limits (e.g., Integer.MAX_VALUE for cached pool) helps avoid resource exhaustion.
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.
Programmer DD
A tinkering programmer and author of "Spring Cloud Microservices in Action"
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.
