Backend Development 18 min read

How to Ensure Cache‑Database Consistency: Strategies, Pitfalls, and Best Practices

This article examines data consistency between Redis cache and MySQL database, explains common cache execution strategies such as Cache‑Aside, Read‑Through, Write‑Through, and Write‑Behind, analyzes four update sequences for consistency risks, and proposes solutions like delayed double‑delete, transactional guarantees, retry mechanisms, and binlog‑based cache invalidation.

Architecture & Thinking
Architecture & Thinking
Architecture & Thinking
How to Ensure Cache‑Database Consistency: Strategies, Pitfalls, and Best Practices

1 Introduction

1.1 Concept of Data Consistency

Data consistency between cache and database means the data stored in the cache must be identical to the data stored in the database. If the cache contains a value, the cached value must equal the database value; if the cache lacks the data, the database must hold the latest value. Consistency includes two cases:

When the cache has data, the cached value must be the same as the database value.

When the cache has no data, the database value must be the latest.

If any of the following occurs, inconsistency exists:

The cache holds data that differs from the database.

Stale data exists in either cache or database, causing a thread to read outdated data.

1.2 Causes of Inconsistency

Cache (Redis) and database (MySQL) are separate systems, so any write to one must be coordinated with the other. Failures can happen due to:

Database update errors.

Cache refresh mechanism errors.

Concurrent requests leading to ordering issues.

Improper consistency strategy selection.

Maintaining consistency requires appropriate strategies such as 2PC, Paxos, distributed locks, and careful handling of errors and operation ordering.

2 Cache Execution Strategies

We first review common cache execution strategies and then analyze which best guarantees consistency.

Cache‑Aside (Cache‑Side): read from cache, fall back to DB, write to cache; write to DB then update cache.

Read‑Through: similar to Cache‑Aside but the cache automatically loads missing data from the DB.

Write‑Through: writes go to both cache and DB synchronously.

Write‑Behind: writes are asynchronously propagated to cache and DB.

Update‑In-Place: updates cache directly without deleting old data.

Write‑Back: update cache first, then asynchronously update DB.

Partitioning: divide cache into partitions with different strategies.

2.1 Cache‑Aside

Cache‑Aside is the most widely used pattern. The application handles all reads and writes to both cache and DB.

2.1.1 Read Operation

Steps:

Attempt to read from cache; if hit, return.

If miss, read from DB, then populate cache for future reads.

Go pseudo‑code implementation:

<code>func main() {
    // Try to get from cache
    cacheValue := getFromCache("testinfo")
    if cacheValue != "" {
        return cacheValue
    } else {
        // Cache miss, fetch from DB
        cacheValue = getDataFromDB()
        // Write to cache
        setInCache(cacheValue)
        return cacheValue
    }
}
</code>

2.1.2 Update Operation

Steps:

Update the database first.

Either update the cache or invalidate it (write‑through).

Because high‑frequency updates can cause race conditions, invalidating the cache (deleting) is often preferred for performance and safety.

<code>func main() {
    _, err = db.Save(&user) // Save updated data to DB
    if err != nil {
        log.Fatal(err)
    } else {
        // After successful DB update, delete cache
        err = deleteCache(id)
    }
}
</code>

Overall advantage: Cache‑Aside improves performance by reducing DB load, while also enhancing reliability and consistency when used correctly.

2.2 Read‑Through

When the cache misses, the system reads from the DB, writes the result into the cache, and returns it. The cache component handles synchronization, which can increase DB load.

2.3 Write‑Through

Writes are directed to the cache, which then synchronously propagates them to the DB, shifting failure handling to the cache layer.

2.4 Write‑Behind

Writes are asynchronously applied to both cache and DB, improving write performance but risking inconsistency.

3 Consistency under Cache‑Aside

In business scenarios, Cache‑Aside is most common. Reads are safe, but writes can cause inconsistency depending on the order of DB and cache updates. Four possible sequences are examined:

Update cache first, then DB.

Update DB first, then cache.

Delete cache first, then update DB.

Update DB first, then delete cache.

We evaluate atomicity and high‑concurrency consistency for each.

3.1 Update Cache First, Then DB

If the cache update succeeds but the DB update fails, the cache becomes dirty, leading to incorrect reads.

3.2 Update DB First, Then Cache

In high‑concurrency, race conditions can cause the cache to hold an older value than the DB.

3.3 Delete Cache First, Then Update DB

Network delays can cause the cache to be repopulated with stale data before the DB update completes, resulting in inconsistency.

3.4 Update DB First, Then Delete Cache

This approach may briefly expose stale reads, but the subsequent cache deletion ensures that future reads fetch the latest DB value, making it the most reliable of the four.

4 Consistency Solutions

4.1 Delayed Double‑Delete

To mitigate the “delete‑then‑update DB” case, perform a second cache deletion after the DB update, with a short sleep interval.

4.2 Transaction Guarantees

Wrap cache deletion and DB update in a transaction so that failure of either operation rolls back the other.

4.3 Cache Deletion Retry Mechanism

If double‑delete fails, log the incident or use a message queue to trigger an asynchronous cleanup service.

4.4 Binlog‑Based Independent Deletion

Leverage DB binlog (e.g., via Canal) to capture changes and let a dedicated cache‑deletion service consume the events and delete keys.

5 Summary

Cache‑Aside is the most commonly used pattern.

Read strategy: cache‑hit returns; miss reads DB, writes cache, returns.

Write strategy: update DB first, then delete cache.

In practice, delayed double‑delete and retry mechanisms are recommended to ensure consistency.

distributed systemsRedisCache Consistencycache asidedatabase synchronization
Architecture & Thinking
Written by

Architecture & Thinking

🍭 Frontline tech director and chief architect at top-tier companies 🥝 Years of deep experience in internet, e‑commerce, social, and finance sectors 🌾 Committed to publishing high‑quality articles covering core technologies of leading internet firms, application architecture, and AI breakthroughs.

0 followers
Reader feedback

How this landed with the community

login Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.