Cache Update Strategies and Concurrency Control in Backend Systems

The article analyzes the challenges of keeping cache and database consistent after write operations, evaluates four update‑order strategies, discusses their concurrency pitfalls, and presents practical solutions such as CAS, distributed locks, asynchronous updates, and delayed double‑delete techniques.

Top Architect
Top Architect
Top Architect
Cache Update Strategies and Concurrency Control in Backend Systems

When a write operation updates the database, the cache must be refreshed to keep the data consistent; otherwise, stale data may be served.

Four combinations of update order (database‑then‑cache delete, database‑then‑cache update, cache delete‑then‑database, cache update‑then‑database) are examined, each exposing risks like throughput impact, concurrent safety issues, failure handling, and difficulty of fault detection.

Two primary ways to update the cache are discussed: deleting expired entries so the next read repopulates the cache, and directly overwriting the cache with new data.

Concurrency problems, often called "race conditions" or "抢跑", can cause data inconsistency when the later thread finishes before the earlier one.

Solution 1: CAS (Compare‑And‑Swap) – an optimistic lock that writes only if the cached value has not changed. Example implementation:

func CAS(oldVal, newVal) {
    if cache.get() == oldVal {
        cache.set(newVal)
    }
}

CAS can prevent concurrent errors in the "database‑then‑cache update" scenario by ensuring only one thread updates the cache.

Solution 2: Distributed Lock – a pessimistic lock that forces threads to acquire an exclusive lock before accessing the database or cache, guaranteeing serial execution at the cost of higher overhead.

Solution 3: Asynchronous Update – let the API server write to the database while a separate thread subscribes to binlog events and updates the cache, reducing write‑path latency.

Solution 4: Delayed Double Delete – after updating the database, delete the cache, wait a short period, then delete it again to mitigate the window where a read might fetch stale data.

Each method balances complexity, performance, and safety; the choice depends on the specific workload and consistency requirements.

Original Source

Signed-in readers can open the original source through BestHub's protected redirect.

Sign in to view source
Republication Notice

This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactadmin@besthub.devand we will review it promptly.

backendCacheCASConsistencydistributed-lock
Top Architect
Written by

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.

0 followers
Reader feedback

How this landed with the community

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.