Кэширование в C#: Redis, Memcached и встроенные решения от А до Я

Онлайн-тренажер Python для начинающих

Изучайте Python легко и без перегрузки теорией. Решайте практические задачи с автоматической проверкой, получайте подсказки на русском языке и пишите код прямо в браузере — без необходимости что-либо устанавливать.

Начать курс

Кэширование в C#: Redis, Memcached и встроенные решения — полное руководство

В современной веб-разработке производительность приложения — один из ключевых факторов успеха. Кэширование позволяет существенно снизить нагрузку на базу данных и ускорить отклик системы. В экосистеме C# (.NET) разработчику доступны три основных подхода: встроенное кэширование в памяти (IMemoryCache), распределенные решения (IDistributedCache) и внешние серверы кэширования, такие как Redis и Memcached. В этой статье мы разберем каждый из них от теории до практических примеров кода.

1. Встроенное кэширование в .NET: IMemoryCache

Встроенное кэширование — это самый простой и быстрый способ временного хранения данных. В ASP.NET Core оно реализовано через интерфейс IMemoryCache. Данные хранятся в оперативной памяти одного процесса, что обеспечивает минимальную задержку.

Когда использовать:

  • Данные не нужно синхронизировать между несколькими серверами.
  • Объем кэшируемых данных невелик.
  • Требуется максимальная производительность без настройки внешних сервисов.

Пример реализации:

using Microsoft.Extensions.Caching.Memory;

public class WeatherService
{
    private readonly IMemoryCache _cache;

    public WeatherService(IMemoryCache cache)
    {
        _cache = cache;
    }

    public async Task<WeatherData> GetWeatherAsync(string city)
    {
        string cacheKey = $"weather_{city}";

        if (!_cache.TryGetValue(cacheKey, out WeatherData data))
        {
            // Данных нет в кэше — загружаем из внешнего источника
            data = await FetchWeatherFromApi(city);

            // Настройка кэша: срок жизни 5 минут
            var cacheOptions = new MemoryCacheEntryOptions()
                .SetAbsoluteExpiration(TimeSpan.FromMinutes(5));

            _cache.Set(cacheKey, data, cacheOptions);
        }

        return data;
    }

    private async Task<WeatherData> FetchWeatherFromApi(string city)
    {
        // Имитация вызова внешнего API
        await Task.Delay(1000);
        return new WeatherData { City = city, Temperature = 22.5 };
    }
}

public class WeatherData
{
    public string City { get; set; }
    public double Temperature { get; set; }
}

Ключевые методы: TryGetValue, Set, Remove. Важно помнить, что IMemoryCache не подходит для микросервисной архитектуры.

2. Распределенное кэширование: IDistributedCache и его провайдеры

Для приложений, работающих на нескольких серверах, необходимо распределенное кэширование. В .NET оно абстрагировано через интерфейс IDistributedCache. Это позволяет легко менять провайдер (Redis, SQL Server, NCache) без изменения бизнес-логики.

Основные методы:

  • GetAsync / SetAsync — для работы с байтами.
  • GetStringAsync / SetStringAsync — для строковых данных.
  • RefreshAsync — сброс таймера скользящего срока жизни.
  • RemoveAsync — удаление записи.

Пример с Redis:

// В Program.cs регистрируем провайдер
builder.Services.AddStackExchangeRedisCache(options =>
{
    options.Configuration = "localhost:6379";
    options.InstanceName = "SampleApp";
});

// Использование в сервисе
public class ProductService
{
    private readonly IDistributedCache _cache;

    public ProductService(IDistributedCache cache)
    {
        _cache = cache;
    }

    public async Task<Product> GetProductAsync(int id)
    {
        string cacheKey = $"product_{id}";
        string cachedData = await _cache.GetStringAsync(cacheKey);

        if (cachedData != null)
        {
            return JsonSerializer.Deserialize<Product>(cachedData);
        }

        // Загрузка из БД
        var product = await GetProductFromDatabase(id);
        string serialized = JsonSerializer.Serialize(product);

        var options = new DistributedCacheEntryOptions()
            .SetSlidingExpiration(TimeSpan.FromMinutes(10));

        await _cache.SetStringAsync(cacheKey, serialized, options);
        return product;
    }
}

3. Redis — мощный сервер кэширования

Redis — это in-memory хранилище данных, которое часто используется как кэш, брокер сообщений и база данных. В контексте C# он поддерживается через библиотеку StackExchange.Redis или через встроенный провайдер IDistributedCache.

Преимущества Redis:

  • Поддержка сложных структур данных (списки, хеши, множества).
  • Pub/Sub для обмена сообщениями.
  • Персистентность (сохранение на диск).
  • Кластеризация и высокая доступность.

Пример прямого использования StackExchange.Redis:

using StackExchange.Redis;

public class RedisCacheService
{
    private readonly ConnectionMultiplexer _redis;
    private readonly IDatabase _db;

    public RedisCacheService(string connectionString)
    {
        _redis = ConnectionMultiplexer.Connect(connectionString);
        _db = _redis.GetDatabase();
    }

    public async Task SetAsync<T>(string key, T value, TimeSpan expiry)
    {
        string json = JsonSerializer.Serialize(value);
        await _db.StringSetAsync(key, json, expiry);
    }

    public async Task<T> GetAsync<T>(string key) where T : class
    {
        string json = await _db.StringGetAsync(key);
        return json != null ? JsonSerializer.Deserialize<T>(json) : null;
    }

    public async Task RemoveAsync(string key)
    {
        await _db.KeyDeleteAsync(key);
    }
}

Типичные сценарии: кэширование сессий, ограничение частоты запросов (rate limiting), кэширование результатов тяжелых запросов.

4. Memcached — легковесная альтернатива

Memcached — это распределенная система кэширования, ориентированная на простоту и скорость. В отличие от Redis, Memcached не поддерживает сложные типы данных и персистентность, но требует меньше ресурсов.

Особенности Memcached:

  • Только хранение ключ-значение (максимум 1 МБ на запись).
  • Автоматическое удаление устаревших данных (LRU).
  • Нет репликации (все данные хранятся на одном серве

Блоги

Рекомендаций по книгам