В какой момент нужно инвалидировать или вытеснять кеш в Redis?

Ответ

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

1. Инвалидация по времени (TTL - Time to Live)

Используйте, когда данные могут быть "слегка устаревшими" и их обновление предсказуемо.

// Установка ключа с автоматическим истечением через 5 минут
IDatabase cache = connection.GetDatabase();
cache.StringSet("user:profile:123", jsonData, TimeSpan.FromMinutes(5));

Когда применять: Для данных, которые меняются нечасто (профили пользователей, каталоги товаров, статичный контент).

2. Явная (активная) инвалидация

Удаляйте ключ сразу при изменении исходных данных. Это гарантирует консистентность.

// После успешного обновления записи в БД
await _userRepository.UpdateAsync(user);
await cache.KeyDeleteAsync("user:profile:" + user.Id); // Немедленная инвалидация

Когда применять: Для критически важных данных, где устаревшая информация недопустима (баланс счета, статус заказа, актуальная цена).

3. Паттерн "Write-Through" или "Cache-Aside" с инвалидацией

Кеш обновляется синхронно с записью в основное хранилище.

public async Task UpdateProductAsync(Product product)
{
    // 1. Обновить базу данных
    await _dbContext.SaveChangesAsync();
    // 2. Обновить кеш (или удалить, чтобы следующее чтение загрузило свежие данные)
    var cacheKey = $"product:{product.Id}";
    await _cache.StringSetAsync(cacheKey, JsonSerializer.Serialize(product), TimeSpan.FromHours(1));
}

4. Вытеснение политиками Redis (LRU, LFU)

Redis автоматически удаляет ключи при нехватки памяти, согласно настройке maxmemory-policy (например, allkeys-lru). Когда полагаться: Это стратегия "последней линии обороны", а не основная. Всегда лучше управлять сроком жизни ключей явно.

Рекомендации:

  • Комбинируйте подходы: Используйте TTL как "страховку" даже при явной инвалидации.
  • Мониторьте hit rate: Низкий процент попаданий в кеш может указывать на слишком короткий TTL или неэффективные ключи.
  • Используйте паттерны: Для сложных сценариев рассмотрите паттерны Cache-Aside, Read-Through или Write-Behind.

Ответ 18+ 🔞

Давай разберём эту тему про кеш, как взрослые люди, без этих ваших заумных терминов, которые только в документациях красиво смотрятся.

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

1. По таймеру (TTL) — "автопилот для ленивых" Ставишь время — и забыл. Ключ сам сдохнет через заданный промежуток. Как молоко в холодильнике с датой истечения.

cache.StringSet("user:profile:123", jsonData, TimeSpan.FromMinutes(5)); // Живёт 5 минут и в пизду

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

2. Ручная инвалидация — "сам всё контролирую, мать его" Изменились данные в главной базе? Немедленно выковыривай старый кеш. Чтобы следующий запрос поднял свежачок.

await _userRepository.UpdateAsync(user);
await cache.KeyDeleteAsync("user:profile:" + user.Id); // Бдыщ! И нет ключа.

Юзать, когда: Консистентность важнее всего. Финансы (баланс), статусы заказов ("оплачено" или "хуёво"), акционные цены. Здесь просроченные данные — это прямой путь в жопу, причём в самую глубокую.

3. Паттерн "обновил в базе — сразу в кеш засунь" Чуть более продвинутая версия ручного управления. Не просто удалил старьё, а сразу положил новое. Чтобы следующий бедолага, который запросит эти данные, не ходил в базу, а взял уже готовое и свежее.

await _dbContext.SaveChangesAsync(); // В базу записал
var cacheKey = $"product:{product.Id}";
await _cache.StringSetAsync(cacheKey, JsonSerializer.Serialize(product), TimeSpan.FromHours(1)); // И в кеш сразу

4. "А хуй его знает, пусть Redis сам разбирается" (LRU/LFU) Настраиваешь политику вытеснения в Redis (типа allkeys-lru). Когда память заканчивается, он начинает выкидывать ключи, которые давно не использовались. Это как приходишь на кухню, а там места нет, — начинаешь безжалостно выкидывать старые консервы и пустые банки из-под пива. На что похоже: На стратегию "последней надежды". Нельзя на это полагаться как на основной метод. Это спасательный круг, когда всё уже хуёво.

Итоговые советы, чтобы не обосраться:

  • Страхуйся. Даже если используешь ручную инвалидацию, накидывай TTL. Вдруг твой код удаления ключа ебнулся и не сработал? TTL подстрахует и через час-другой почистит мусор.
  • Следи за попаданиями. Смотри на метрику hit rate. Если она низкая, значит, кеш почти не работает. Возможно, TTL слишком короткий, или ключи составлены криво, или данные вообще не те кешируешь.
  • Выбирай паттерн по ситуации. Не надо из пушки по воробьям. Если данные не критические — хватит и TTL. Если от актуальности зависит денежный поток — будь добр, инвалидируй вручную и сразу.

Вот и вся философия. Не усложняй там, где не надо, но и не расслабляйся там, где это чревато пиздецом.