When to Update Redis Cache: DB‑First vs Cache‑First Strategies Explained
This article examines the consistency challenges of using Redis as a cache, compares three update strategies—updating the database before the cache, deleting the cache before updating the database, and updating the database then deleting the cache—analyzes their pitfalls, and presents practical solutions such as delayed double‑delete, asynchronous retries, and binlog‑driven cache invalidation.
Cache Consistency: Should the Database Be Updated Before the Cache?
Redis is widely used as a high‑performance cache, but keeping cache and database consistent after write operations is a common source of bugs. The article explores three typical update strategies and why some of them are problematic.
Three update strategies are discussed:
Update the database first, then update the cache.
Delete the cache first, then update the database.
Update the database first, then delete the cache.
(1) Update Database First, Then Update Cache
This approach is generally discouraged because concurrent writes can cause race conditions: two threads may update the database in different orders, and the later cache update can overwrite the earlier one, leading to stale data. It also wastes resources when write‑heavy, read‑light workloads repeatedly recalculate cache values.
(2) Delete Cache First, Then Update Database
Deleting the cache before the write can still produce inconsistency. If a read request occurs between the cache deletion and the database write, it may fetch stale data from the database and repopulate the cache with the old value. Without an expiration policy, the stale data persists.
To mitigate this, a delayed double‑delete strategy is recommended:
public void write(String key, Object data) {
redis.delKey(key);
db.updateData(data);
Thread.sleep(1000);
redis.delKey(key);
}The first delete removes the old cache entry, the database is updated, then after a short pause (chosen based on the expected read‑operation latency plus a safety margin) the cache is deleted again to clear any data that might have been written by concurrent reads.
(3) Update Database First, Then Delete Cache (Cache‑Aside Pattern)
This is the classic Cache‑Aside pattern: write to the database, then invalidate the cache. Facebook’s "Scaling Memcache at Facebook" paper endorses this approach. It avoids the race condition of the first strategy because the cache is never written directly after a write; instead, the next read will repopulate it with fresh data.
Even with this pattern, a brief window exists where a concurrent read may fetch stale data before the cache is invalidated. The probability is low because database reads are typically faster than writes, but if strict consistency is required, the delayed double‑delete or asynchronous invalidation can be applied.
How to handle cache‑delete failures?
If the second delete fails, stale data may remain. Two robust solutions are proposed:
Send the cache‑key to a message queue after a failed delete and retry until success.
Subscribe to the database binlog (e.g., using Canal), extract the affected keys, and retry deletion via a background worker.
Additional recommendations include staggering cache expiration times to avoid cache‑avalanche, using distributed locks for cache‑miss handling, and ensuring high availability of the Redis cluster.
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.
Java Interview Crash Guide
Dedicated to sharing Java interview Q&A; follow and reply "java" to receive a free premium Java interview guide.
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.
