You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
When a popular cache entry expires, many concurrent requests hit the database:
126
+
When a popular cache entry expires, many concurrent requests hit the database simultaneously, overwhelming it. Solutions include:
201
127
202
-
```python
203
-
# Problem: Multiple requests fetch same data simultaneously
204
-
# Solution: Use locks or probabilistic early expiration
205
-
defget_user_with_lock(user_id):
206
-
cache_key =f'user:{user_id}'
207
-
lock_key =f'{cache_key}:lock'
208
-
209
-
cached_user = r.get(cache_key)
210
-
if cached_user:
211
-
return json.loads(cached_user)
212
-
213
-
# Try to acquire lock
214
-
if r.set(lock_key, '1', nx=True, ex=10):
215
-
try:
216
-
user = fetch_from_database(user_id)
217
-
r.setex(cache_key, 3600, json.dumps(user))
218
-
return user
219
-
finally:
220
-
r.delete(lock_key)
221
-
else:
222
-
# Wait for lock holder to populate cache
223
-
time.sleep(0.1)
224
-
return get_user_with_lock(user_id)
225
-
```
128
+
-**Lock-based approach**: Use Redis `SET` with `NX` (only if not exists) to create a lock. Only the lock holder fetches from the database; others wait.
129
+
-**Probabilistic early expiration**: Refresh cache entries before they expire based on a probability calculation.
130
+
-**Stale-while-revalidate**: Serve stale data while refreshing in the background.
226
131
227
132
### Null Value Caching
228
-
Cache null values to prevent repeated database queries:
133
+
When a key doesn't exist in the database, cache a null marker to prevent repeated database queries:
229
134
230
-
```python
231
-
defget_user_with_null_cache(user_id):
232
-
cache_key =f'user:{user_id}'
233
-
cached = r.get(cache_key)
234
-
235
-
if cached =='NULL':
236
-
returnNone# User doesn't exist
237
-
238
-
if cached:
239
-
return json.loads(cached)
240
-
241
-
user = fetch_from_database(user_id)
242
-
243
-
if user isNone:
244
-
r.setex(cache_key, 300, 'NULL') # Cache null for 5 minutes
245
-
else:
246
-
r.setex(cache_key, 3600, json.dumps(user))
247
-
248
-
return user
249
-
```
135
+
- Store a special marker (e.g., `"NULL"`) in Redis with a short TTL (e.g., 5 minutes)
136
+
- Check for this marker before querying the database
137
+
- This prevents "cache misses" from repeatedly hitting the database for non-existent keys
138
+
139
+
### Other Common Issues
140
+
141
+
-**Inconsistent TTLs**: Different data types should have different TTLs based on how frequently they change
0 commit comments