Redis Cache and Database Consistency
Caching improves performance and reduces database load, but introduces potential inconsistencies between cached data and the database. Inconsistent data leads to stale reads from the cache.
Non-Concurrency Scenarios
Update Cache First, Then Database
If cache udpate succeeds but database update fails, the cache holds new data while the database retains old data, causing inconsistency.
Update Database First, Then Cache
If database udpate succeeds but cache update fails, the database contains new data while the cache holds old data. Subsequent reads return stale data until cache expiration.
Concurrency Scenarios
Delete Cache First, Then Update Database
Concurrent read/write operations may cause:
- Thread A deletes cache (preparing to update X=2)
- Thread B reads cache (miss), fetches old value from DB (X=1)
- Thread A updates DB (X=2)
- Thread B writes old value to cache (X=1) Result: Cache holds stale data (X=1) while DB has new value (X=2).
Update Database First, Then Delete Cache
Scenario:
- Cache empty for X (DB X=1)
- Thread A reads DB (X=1)
- Thread B updates DB (X=2) and deletes cache
- Thread A writes old value to cache (X=1) Result: Cache holds stale data (X=1) while DB has new value (X=2).
Recommended Solution: Delayed Double Deletion
- Delete cache
- Update database
- Sleep for a calculated duration (accounts for replication delay between DB and Redis)
- Delete cache again
This approach addresses replication delays:
- First deletion prevents imediate stale reads during update
- Sleep allows time for database changes to propagate to replicas
- Second deletion removes any stale data written during the update window
Implementation flow:
- Service deletes Redis primary data
- Service updates MySQL primary data
- Service pauses (awaiting MySQL→Redis replication)
- Service deletes Redis primary data again
- Subsequent reads trigger cache misses, fetching fresh data from MySQL replica and repopulating Redis