BlackHorse Rating Merchant Cache
Consistency
Cache Update Strategies
- Memory Eviction: Redis automatically evicts data when memory is low; cache updated on next request.
- TTL Expiry: Set TTL on cached data; deleted automatically when expired; updated on next request.
- Active Update: Update cache simultaneously with database modification.
Cache-Database Consistency
Concurrent requests can cause inconsistency regardless of update order (cache first or database first).
Use Cache Aside strategy: cache only updated during read operations.
- Write strategy: When modifying data, update database and delete cache.
- Read strategy: When reading data, if cache miss, read from database and update cache.
Update-Then-Delete (Delayed Double Delete)
Thread A reading, Thread B updating simultaneously:
- Thread A cache miss, reads DB x=20
- Thread B updates DB x=21
- Thread B deletes cache (first delete)
- Thread A writes stale data to cache x=20
- Thread B delays briefly then executes second delete (active, not passive)
- Low probability: steps 1-4 usually complete faster than DB query+update.
- Delay time (e.g., 500ms) should exceed “query DB + write cache” duration (typically < 100ms).
- Proper delay covers Thread A’s stale write (step 4).
- Repeated deletion is safe and idempotent even without conflicts.
What if cache deletion fails?
Use @Transactional. If cache deletion fails, database update should roll back. Other methods
Shop Cache Implementation
Use active update + TTL expiry strategy.
- Query shop by ID: if cache miss, read DB, write to cache with TTL.
- When modifying data: update database first, then delete cache.
Store Shop object as JSON string in Redis. Suitable for complex objects with infrequent updates.
For frequent updates, consider storing as Redis hash.
Cache Utility Class
| |
StringRedisTemplate is auto-configured by Spring Boot based on application.yml. Spring creates a singleton instance.
CacheClient is a @Component bean. Spring injects StringRedisTemplate via constructor injection.
Cache Penetration
Requests for data that doesn’t exist in cache or database. High volume can overload database.
- Cache null values: When DB query returns empty, store null in Redis.
- Bloom Filter: Pre-load all existing product IDs into bloom filter.
- Check bloom filter first; if not present, return “not exists”; otherwise proceed to cache/DB.
Cache Avalanche
Massive cache key expiry/Redis downtime simultaneously, flooding database with requests. Solution: Set random expiry times; use Redis cluster.
Cache Breakdown
Hot key with complex rebuild logic expires. Many concurrent requests hit database simultaneously. Solution: Logical expiry + mutual exclusion lock.
When Redis cache expires for a merchant, attempt to acquire lock. If successful, spawn thread to rebuild cache while current thread returns stale data immediately.