Какие решения вы использовали для кеширования данных в C#?

Ответ

Выбор решения для кеширования зависит от масштаба приложения и требований. Вот основные инструменты, которые я применял:

1. IMemoryCache (для кеша в памяти процесса) Идеально для быстрого кеширования данных в рамках одного экземпляра приложения (не распределенного).

// Внедрение через DI
public class MyService
{
    private readonly IMemoryCache _cache;
    public MyService(IMemoryCache cache) => _cache = cache;

    public string GetCachedData()
    {
        return _cache.GetOrCreate("myKey", entry =>
        {
            entry.AbsoluteExpirationRelativeToNow = TimeSpan.FromMinutes(10);
            return ExpensiveDatabaseCall(); // Данные кешируются на 10 минут
        });
    }
}

2. IDistributedCache (для распределенного кеша) Используется, когда несколько экземпляров приложения должны разделять общий кеш (например, в веб-ферме). Поддерживает разные бэкенды:

  • Redis (наиболее популярный, высокопроизводительный).
  • SQL Server.
  • NCache.

3. Атрибут [ResponseCache] в ASP.NET Core Для кеширования HTTP-ответов на уровне контроллера или действия, используя заголовки Cache-Control.

[HttpGet]
[ResponseCache(Duration = 60)] // Кеширует ответ на 60 секунд
public IActionResult Get() { ... }

4. Lazy<T> для ленивой инициализации с кешированием результата Полезно для тяжелых в создании объектов, которые нужны только при первом обращении.

private readonly Lazy<ExpensiveService> _service = new Lazy<ExpensiveService>(() => new ExpensiveService());

Критерии выбора: IMemoryCache — для простых сценариев в одном процессе; IDistributedCache с Redis — для масштабируемых и отказоустойчивых систем. Всегда важно настраивать политику срока жизни (TTL) и продумывать стратегию инвалидации кеша.

Ответ 18+ 🔞

Ну, смотри, выбор кеша — это как выбор машины: можно на жигулях кататься, а можно на мерседесе, но если ты в пробке — всем пиздец. Вот как я обычно решаю:

1. IMemoryCache (кеш прямо в памяти процесса) Это как твоя личная тумбочка у кровати — быстро, под рукой, но если комната не одна (несколько экземпляров приложения), то в другой комнате про эту тумбочку нихуя не знают. Идеально для мелких, быстрых штук в рамках одного процесса.

// Внедряешь через DI, как обычно
public class MyService
{
    private readonly IMemoryCache _cache;
    public MyService(IMemoryCache cache) => _cache = cache;

    public string GetCachedData()
    {
        // GetOrCreate — магия, чтобы не писать кучу if'ов
        return _cache.GetOrCreate("myKey", entry =>
        {
            // Ставишь срок годности, а то протухнет
            entry.AbsoluteExpirationRelativeToNow = TimeSpan.FromMinutes(10);
            return ExpensiveDatabaseCall(); // Грузишь из базы и кешируешь на 10 минут
        });
    }
}

2. IDistributedCache (распределенный кеш) А вот это уже общий холодильник на несколько квартир (экземпляров приложения). Все туда кладут, все оттуда берут. Бэкенды разные:

  • Redis — это как холодильник премиум-класса, быстрый, надежный, все его любят.
  • SQL Server — как холодильник, который ещё и умеет считать, но иногда тупит.
  • NCache — тоже вариант, но я чаще с Redis работаю, честно.

3. Атрибут [ResponseCache] в ASP.NET Core Это когда тебе нужно, чтобы ответ от сервера кешировался прямо у клиента или на прокси. По сути, игра с заголовками Cache-Control. Просто, но не для всех случаев.

[HttpGet]
[ResponseCache(Duration = 60)] // Говоришь браузеру: "держи это 60 секунд, не дергай меня"
public IActionResult Get() { ... }

4. Lazy<T> для ленивой инициализации Представь, что у тебя есть здоровенный, ебучо тяжёлый сервис, который создаётся долго. Lazy<T> — это как сказать: "не создавай его, пока реально не попросят, а создал — держи до конца". Однократное кеширование, по сути.

private readonly Lazy<ExpensiveService> _service = new Lazy<ExpensiveService>(() => new ExpensiveService());
// Первый вызов _service.Value — создаст. Второй и дальше — отдаст уже созданное.

Итог, чувак: Если приложение — одинокий волк (один инстанс), бери IMemoryCache, не заморачивайся. Если это стая волков (куча инстансов за балансировщиком), то без IDistributedCache (читай: Redis) — нихуя не синхронизируешь, будет бардак. И главное — всегда думай, когда этот кеш чистить! А то накопишь старого хлама, а потом удивляешься, почему данные, блядь, как неделю назад. TTL — твой лучший друг.