Вопрос проверяет знание различных методов принудительного обновления или удаления данных из кэша для обеспечения их актуальности.
Основные стратегии инвалидации кэша — это инвалидация по TTL (автоматическое удаление по истечении времени) и явная инвалидация. Явная инвалидация происходит при изменении данных в основном источнике (например, в базе данных), чтобы кэш всегда содержал актуальную информацию. Часто используется комбинация TTL для защиты от "протухания" данных и явной инвалидации для мгновенного обновления.
Инвалидация кэша — это процесс пометки данных в кэше как недействительных с целью их последующего обновления.
Основные стратегии:
Инвалидация по времени (TTL):
Самый простой способ. Кэш автоматически удаляет запись после истечения заданного времени.
Плюсы: Простота реализации, не требует дополнительной логики.
Минусы: Данные могут быть устаревшими до истечения TTL.
Явная (активная) инвалидация:
Приложение явно удаляет или обновляет данные в кэше, когда изменяются соответствующие данные в источнике (например, в БД).
Пример: После обновления профиля пользователя в базе данных приложение отправляет команду на удаление ключа user:123 из кэша.
Плюсы: Обеспечивает высокую консистентность данных.
Минусы: Сложнее в реализации, требует отслеживания всех операций, меняющих данные.
Инвалидация по событию (Event-Driven Invalidation):
Это подвид явной инвалидации. Приложение публикует событие о изменении данных (например, с помощью Spring Events или брокера сообщений like RabbitMQ), а специальный слушатель обрабатывает это событие и инвалидирует соответствующий кэш.
Пример комбинированной стратегии на псевдокоде:
@Service
public class UserService {
@CacheEvict(value = "users", key = "#user.id") // Явная инвалидация при обновлении
public User updateUser(User user) {
// 1. Обновляем данные в БД
userRepository.save(user);
// 2. Аннотация @CacheEvict гарантирует, что старые данные удалятся из кэша
}
@Cacheable(value = "users", key = "#id", ttl = "300") // Кэширование с TTL 5 минут
public User getUserById(Long id) {
// Этот метод выполнится, только если данных нет в кэше
return userRepository.findById(id).orElse(null);
}
}Вывод:
Для большинства сценариев оптимальна гибридная стратегия: использовать TTL как "страховочную сетку" на случай сбоев в явной инвалидации, а основным механизмом делать явную инвалидацию при изменении данных.