Что такое кеширование?

«Что такое кеширование?» — вопрос из категории Архитектура, который задают на 25% собеседований C# Разработчик. Ниже — развёрнутый ответ с разбором ключевых моментов.

Ответ

Кеширование — это техника временного сохранения часто запрашиваемых или вычисляемых данных в быстродоступном хранилище (кеше) для ускорения последующих обращений и снижения нагрузки на первичные источники (базу данных, внешние API, файловую систему).

Основные цели:

  • Повышение производительности: Сокращение времени отклика за счет доступа к данным из памяти.
  • Снижение нагрузки: Уменьшение количества запросов к медленным или перегруженным источникам данных.
  • Повышение масштабируемости: Возможность обслуживать больше пользователей с теми же ресурсами.

Практический пример в C# с IMemoryCache:

using Microsoft.Extensions.Caching.Memory;

public class DataService
{
    private readonly IMemoryCache _cache;
    private readonly TimeSpan _cacheDuration = TimeSpan.FromMinutes(5);

    public DataService(IMemoryCache cache) => _cache = cache;

    public async Task<string> GetExpensiveDataAsync(string key)
    {
        // Пытаемся получить данные из кеша
        if (!_cache.TryGetValue(key, out string cachedData))
        {
            // Данных в кеше нет — получаем их из источника (например, БД)
            cachedData = await FetchFromDatabaseAsync(key);

            // Сохраняем в кеш с политикой срока действия
            var cacheOptions = new MemoryCacheEntryOptions()
                .SetAbsoluteExpiration(_cacheDuration);

            _cache.Set(key, cachedData, cacheOptions);
        }
        return cachedData;
    }
}

Типы и стратегии кеширования:

  • In-Memory Cache: Данные хранятся в памяти процесса приложения (быстро, но не распределено). Пример: IMemoryCache в .NET.
  • Распределенный кеш: Данные хранятся во внешнем хранилище, доступном для нескольких экземпляров приложения. Примеры: Redis, Memcached.
  • Кеширование на стороне клиента: Использование HTTP-заголовков (Cache-Control, ETag) для кеширования в браузере или CDN.

Ключевые проблемы и их решение:

  1. Инвалидация кеша: Определение момента, когда данные в кеше становятся неактуальными.
    • По времени (TTL): Просто, но данные могут устареть раньше срока.
    • По событию: Кеш очищается при изменении данных в источнике (более сложно, но точнее).
  2. Консистентность: Гарантия того, что данные в кеше соответствуют данным в источнике. Часто требуется компромисс между производительностью и актуальностью.
  3. Стратегии записи:
    • Cache-Aside (Lazy Loading): Приложение явно читает из кеша и обновляет его при промахе (как в примере выше).
    • Write-Through: Запись данных всегда происходит сначала в кеш, а затем синхронно в источник данных.
    • Write-Back (Write-Behind): Запись происходит в кеш, а обновление источника откладывается, что повышает производительность, но риск потери данных.