Кэширование: IMemoryCache, IDistributedCache, HybridCache, output caching
↑ 7.1 Производительность .NET и кэширование · ← Предыдущая · → Следующая
Зачем это на собесе
Кэш — самый частый способ ускорения и самый частый источник багов: инвалидация, устаревание, stampede.
Объяснение
| Тип | Где хранится | Когда |
|---|---|---|
IMemoryCache | память процесса | быстро, но у каждой реплики свой кэш |
IDistributedCache (Redis, SQL) | внешнее хранилище | общий кэш реплик, сериализация, сетевая задержка |
HybridCache (.NET 9) | L1 память + L2 распределённый | защита от stampede, теги, сериализация из коробки |
| Output caching | готовые HTTP-ответы (см. Кэширование HTTP: ETag, Cache-Control, output caching) | публичные идемпотентные GET |
| HTTP-кэш (CDN, браузер) | вне приложения | статика и публичные данные |
builder.Services.AddHybridCache(o => o.DefaultEntryOptions = new() { Expiration = TimeSpan.FromMinutes(5), LocalCacheExpiration = TimeSpan.FromMinutes(1) });
public async Task<ProductDto> GetAsync(int id, CancellationToken ct) =>
await cache.GetOrCreateAsync($"product:{id}",
async token => await repo.LoadAsync(id, token), // вызывается один раз при промахе, остальные ждут
tags: ["products"], cancellationToken: ct);
await cache.RemoveByTagAsync("products", ct); // инвалидацияЧто кэшировать: дорогие вычисления, редко меняющиеся справочники, ответы внешних API. Что не кэшировать: персональные данные без ключа пользователя, быстро меняющиеся критичные данные.
Нюансы и подводные камни
- Ключ должен включать все параметры, влияющие на результат (пользователь, язык, версия).
- Время жизни и инвалидация: кэш без стратегии инвалидации даёт устаревшие данные.
IMemoryCache.GetOrCreateAsyncне защищает от параллельных вызовов фабрики.- Ограничивайте размер (
SizeLimit), иначе память растёт. - Кэш не должен быть единственным источником: система обязана работать при его недоступности.
- Сериализация в Redis: версионирование формата при обновлении приложения.
Практика
- Добавьте
HybridCacheк справочнику и измерьте нагрузку на БД. - Реализуйте инвалидацию по тегам при изменении данных.
- Проверьте работу при остановке Redis.
Вопросы с ответами
IMemoryCache или Redis?
Память процесса быстрее, но не общая; Redis нужен для общего кэша реплик и больших объёмов.
Что даёт HybridCache?
Двухуровневый кэш с защитой от stampede и тегированной инвалидацией.