Стратегии кэша и инвалидация, cache stampede
↑ 7.1 Производительность .NET и кэширование · ← Предыдущая · → Следующая
Зачем это на собесе
«В компьютерной науке две сложные вещи: инвалидация кэша и именование». Ждут знания паттернов.
Объяснение
| Стратегия | Как работает | Плюсы/минусы |
|---|---|---|
| Cache-aside (lazy) | приложение читает кэш, при промахе грузит из БД и кладёт в кэш | просто, возможны устаревшие данные |
| Read-through | кэш сам загружает данные при промахе | меньше кода в приложении |
| Write-through | запись идёт в кэш и БД синхронно | согласованность, задержка записи |
| Write-behind | запись в кэш, БД обновляется асинхронно | скорость, риск потери |
| Refresh-ahead | обновление до истечения TTL | нет пиков задержки |
Инвалидация:
- TTL: простое и надёжное, допускает устаревание на время TTL.
- Явное удаление при изменении данных (событием, тегом).
- Версионирование ключей (
product:v12:42): старые ключи «умирают» сами. - Событийная: подписка на изменения (CDC, доменные события).
Cache stampede (thundering herd): ключ истёк, тысячи запросов одновременно идут в БД.
| Защита | Идея |
|---|---|
| Блокировка на ключ (single flight) | один запрос обновляет, остальные ждут (HybridCache) |
| Jitter TTL | случайный разброс срока жизни |
| Stale-while-revalidate | отдавать устаревшее, обновляя в фоне |
| Вероятностное раннее обновление | обновление до истечения с вероятностью |
| Кэширование «отрицательных» результатов | защита от запросов несуществующих ключей (cache penetration) |
var lease = await gate.WaitAsync(ct); // SemaphoreSlim на ключ
try { if (!cache.TryGetValue(key, out value)) { value = await load(); cache.Set(key, value, ttl + jitter); } }
finally { gate.Release(); }Нюансы и подводные камни
- Race в cache-aside: конкурентная запись и удаление могут оставить устаревшее значение; TTL — страховка.
- Горячие ключи в Redis перегружают один узел: локальный L1.
- Кэш холодного старта: прогрев после деплоя.
- Утечка данных между пользователями при неверном ключе.
Практика
- Воспроизведите stampede нагрузочным тестом и устраните single flight.
- Реализуйте stale-while-revalidate.
- Добавьте метрики hit ratio и задержки промахов.
Вопросы с ответами
Что такое cache stampede и как бороться?
Массовое одновременное обновление истёкшего ключа; лечат блокировкой на ключ, jitter TTL, фоновым обновлением.
Cache-aside или write-through?
Cache-aside проще и распространён; write-through даёт согласованность ценой задержки записи.