Кэширование: IMemoryCache, IDistributedCache, HybridCache, output caching

↑ 7.1 Производительность .NET и кэширование · ← Предыдущая · → Следующая

Желательно~3 мин чтенияУровень: senior

Зачем это на собесе

Кэш — самый частый способ ускорения и самый частый источник багов: инвалидация, устаревание, 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: версионирование формата при обновлении приложения.

Практика

  1. Добавьте HybridCache к справочнику и измерьте нагрузку на БД.
  2. Реализуйте инвалидацию по тегам при изменении данных.
  3. Проверьте работу при остановке Redis.

Вопросы с ответами

Связанные темы