Cache Consistency Challenges and Update Strategies in Backend Systems
This article explains why caching is essential for high‑traffic services, describes the inherent consistency problems between Redis and MySQL, analyzes four cache‑update strategies with concrete concurrency scenarios, and provides practical recommendations such as using delete‑after‑update, delayed double‑delete, expiration, MQ, and binlog subscription to achieve eventual consistency.
In real‑world business scenarios, data such as orders, members, and payments are persisted in relational databases like MySQL for strong transactional guarantees, but the performance of a single MySQL instance often cannot meet high QPS requirements of large‑scale traffic.
Most read‑heavy workloads (e.g., popular product info, social media posts) benefit from caching, which trades space for time by storing frequently accessed data in faster storage such as Redis or local memory.
Cache Significance
Cache replaces slower database reads with fast memory reads, improving overall read performance.
Consistency Challenges After Introducing Cache
Data now exists simultaneously in Redis and MySQL. If Redis is not updated promptly after a database write, the two stores become inconsistent. The inconsistency window cannot be eliminated completely because there is no transaction spanning both systems.
Even though strong consistency is impossible, achieving eventual consistency with a very short inconsistency window (ideally <1 ms) is acceptable for most applications.
Cache Update Strategies
Four common strategies are discussed:
Update database then update cache.
Update database then delete cache.
Update cache then update database.
Update cache then delete cache.
Each strategy is examined with detailed concurrency examples.
Strategy 1 – Update Database → Update Cache
Typical read‑through logic:
data = queryDataRedis(key);
if (data == null) {
data = queryDataMySQL(key); // cache miss, read from MySQL
if (data != null) {
updateRedis(key, data); // write‑through after DB read
}
}When a write occurs, the database is updated first, then the cache is refreshed. In write‑write concurrency, the order of cache updates can cause temporary inconsistency (e.g., DB values 100→99→98 while cache becomes 100→98→99).
Strategy 2 – Update Database → Delete Cache
Code example:
deleteRedis(key); // invalidate cache
updateMySQL(); // then update DBThis avoids stale cache reads after a DB failure, but in read‑write concurrency a race can still cause a stale read if a read occurs between DB update and cache deletion.
Strategy 3 – Update Cache → Update Database
Code example:
updateRedis(key, data); // update cache first
updateMySQL(); // then update DBIf the DB update fails, the cache holds incorrect data, making this strategy risky.
Strategy 4 – Update Cache → Delete Cache
Code example:
updateRedis(key, data); // write to cache
// later, after DB update
deleteRedis(key); // invalidate cacheThis approach is generally discouraged because it can leave stale data in the cache.
Recommended Approach – Update Database → Delete Cache
Updating the database first and then deleting the cache yields the smallest inconsistency window (the time between DB commit and cache deletion, usually a few milliseconds). This strategy works well for read‑dominant workloads.
Additional Techniques for Stronger Guarantees
1. Cache Expiration : Set a TTL (e.g., 1 minute) so that even if cache invalidation fails, the stale entry will eventually disappear.
2. Message Queue (MQ) for Cache Invalidation :
updateMySQL();
sendMQMessageToDeleteCache(key);MQ provides at‑least‑once delivery, allowing retries if Redis is temporarily unavailable.
3. Delayed Double Delete :
// after DB update
deleteRedis(key);
sleep(N); // N is a short delay
deleteRedis(key); // second delete to cover race readsThe delay N must be tuned; too short renders the second delete ineffective, too long increases the window where stale reads can occur.
4. Binlog Subscription : Listen to MySQL binlog (e.g., using Canal) to detect data changes and trigger cache updates centrally, avoiding scattered cache‑maintenance code.
Multi‑Cache Scenarios
When a single DB record maps to multiple cache keys, a typical update flow is:
updateMySQL(); // update DB record
deleteRedisKey1(); // invalidate homepage cache
updateRedisKey2(); // refresh top‑10 cache
deleteRedisKey3(); // invalidate daily top‑100 cacheBecause each step can fail, using MQ or binlog‑driven processors to handle cache updates asynchronously improves reliability.
Summary of Strategies
Strategy
Concurrent Scenario
Potential Issue
Mitigation
Update DB → Update Cache
Write + Read
Brief read of stale value before cache refresh
Usually acceptable
Update DB → Update Cache
Write + Write
Cache update order differs from DB order, causing inconsistency
Distributed lock (heavy)
Update Cache → Update DB
No concurrency
DB update may fail after cache is updated
Use MQ confirmation
Update Cache → Update DB
Write + Write
Cache update order differs from DB order
Distributed lock (heavy)
Delete Cache → Update DB
Write + Read
Read may fetch stale data before DB update completes
Delayed double delete
Update DB → Delete Cache
Write + Read (cache hit)
Read may see old value between DB commit and cache deletion
Usually negligible
Overall, for most internet services the "update database then delete cache" strategy provides the best trade‑off between consistency and performance.
Final Recommendations
For read‑heavy, write‑light workloads, use "update DB → delete cache".
For read‑write balanced or write‑heavy scenarios, consider "update DB → update cache" with MQ or binlog support.
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.
Top Architect
Top Architect focuses on sharing practical architecture knowledge, covering enterprise, system, website, large‑scale distributed, and high‑availability architectures, plus architecture adjustments using internet technologies. We welcome idea‑driven, sharing‑oriented architects to exchange and learn together.
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.
