Có ba chiến lược, chọn theo mức độ chấp nhận dữ liệu cũ.
1. TTL ngắn (đơn giản nhất) — chấp nhận dữ liệu cũ vài chục giây, không cần invalidate.
from django.core.cache import cache
def top_products():
return cache.get_or_set('top_products', lambda: list(_query()), timeout=60)- **2.
- Xoá key khi dữ liệu đổi** — chính xác nhất nhưng phải nhớ mọi chỗ ghi.
- Đặt trong
transaction.on_commitđể không xoá cache của một transaction rồi rollback.
@receiver(post_save, sender=Product)
def drop_cache(sender, instance, **kwargs):
transaction.on_commit(lambda: cache.delete(f'product:{instance.pk}'))3. Key theo phiên bản — nhúng dấu vết thay đổi vào key (updated_at, số version). Không cần xoá gì; key mới tự trỏ vào ô mới, key cũ tự hết hạn theo TTL. Hợp với dữ liệu phân mảnh theo nhiều tham số (list có filter, phân trang) vì xoá thủ công gần như không khả thi.
Ba điều hay bị bỏ sót:
- Key phải chứa mọi biến làm đổi kết quả — user, locale, tham số filter. Thiếu một cái là dữ liệu người này lộ sang người khác.
- LocMemCache là per-process, mỗi Gunicorn worker một bản riêng, invalidate không lan sang worker khác. Production dùng Redis/Memcached.
- Key nóng hết hạn cùng lúc gây cache stampede — nhiều request cùng tính lại. Giảm bằng TTL có jitter hoặc khoá tính toán bằng cache.add().