Ответ
Контекст: В микросервисе на Spring Boot, отвечающем за каталог товаров, критический эндпоинт GET /products/{id} выполнял тяжелые JOIN-запросы и расчеты, что при высокой нагрузке приводило к задержкам >500 мс и нагрузке на БД.
Предложенное решение: Внедрение двухуровневого кэширования:
- Локальный кэш в памяти (Caffeine) для сверхбыстрого доступа к самым популярным товарам.
- Распределенный кэш (Redis) как единый источник истины для всех экземпляров сервиса, обеспечивающий консистентность данных.
Реализация (упрощенный код):
@Service
@RequiredArgsConstructor
public class ProductService {
private final ProductRepository repository;
private final CacheManager cacheManager;
@Cacheable(value = "products", cacheManager = "redisCacheManager")
public ProductDto getProduct(Long id) {
// Дорогой запрос в БД и преобразование
Product entity = repository.findWithDetailsById(id);
return heavyMappingLogic(entity);
}
@CacheEvict(value = "products", key = "#id")
public void updateProduct(Long id, ProductUpdateDto dto) {
// Инвалидация кэша при обновлении
repository.update(id, dto);
}
}
// Конфигурация двухуровневого кэша
@Configuration
public class CacheConfig {
@Bean
public CacheManager cacheManager() {
CaffeineCacheManager caffeineManager = new CaffeineCacheManager();
caffeineManager.setCaffeine(Caffeine.newBuilder().expireAfterWrite(5, TimeUnit.MINUTES));
return new CompositeCacheManager(caffeineManager, redisCacheManager());
}
}
Результаты:
- Среднее время ответа API упало с 500 мс до 15 мс для кэшированных товаров.
- Нагрузка на БД снизилась на ~60% для read-операций.
- Решение было задокументировано и стало шаблоном для других сервисов команды.