Какой у вас опыт работы с Spring Cache?

Ответ

Опыт работы с Spring Cache включает настройку и использование абстракции кэширования для оптимизации производительности приложений.

Основные возможности и практики:

  1. Декларативное кэширование с помощью аннотаций:

    • @Cacheable – кэширует результат метода.
    • @CachePut – обновляет кэш (например, при сохранении).
    • @CacheEvict – удаляет данные из кэша (например, при удалении).
    • @Caching – группировка нескольких операций с кэшем.
  2. Интеграция с различными провайдерами: Ehcache, Caffeine, Redis, Hazelcast.

  3. Настройка ключей кэширования (SpEL), условий и TTL.

Пример использования в Spring Boot сервисе:

@Service
public class ProductService {
    @Cacheable(value = "products", key = "#id", unless = "#result == null")
    public Product getProductById(Long id) {
        // Дорогой вызов к БД выполняется только при промахе кэша
        return productRepository.findById(id).orElse(null);
    }

    @CachePut(value = "products", key = "#product.id")
    public Product updateProduct(Product product) {
        // Обновляем БД и кэш одновременно
        return productRepository.save(product);
    }

    @CacheEvict(value = "products", key = "#id")
    public void deleteProduct(Long id) {
        productRepository.deleteById(id);
    }
}

Конфигурация в application.yml для использования Caffeine:

spring:
  cache:
    type: caffeine
    caffeine:
      spec: maximumSize=500, expireAfterWrite=10m

Почему это важно: Spring Cache абстрагирует работу с кэшем, позволяя легко менять провайдера и применять кэширование без изменения бизнес-логики, что значительно ускоряет работу приложения при повторяющихся запросах.

Ответ 18+ 🔞

Да ты посмотри, какие удобства придумали, ёпта! Сидишь такой, пишешь код, а тут раз — и можно не ходить каждый раз в базу данных, как последний олух, за одними и теми же данными. Это ж, блядь, волшебство!

Вот смотри, как это работает, на примере какого-нибудь сервиса для товаров. Представь, что у тебя метод, который тащит товар по айдишнику. Без кэша он будет каждый раз, сука, дергать базу, даже если ты за секунду десять раз спросишь про один и тот же товар. А база — она тоже живая, ей, блядь, не похуй!

А теперь — магия. Вешаешь одну аннотацию, и всё.

@Service
public class ProductService {
    @Cacheable(value = "products", key = "#id", unless = "#result == null")
    public Product getProductById(Long id) {
        // Дорогой вызов к БД выполняется только при промахе кэша
        return productRepository.findById(id).orElse(null);
    }
}

Видишь эту @Cacheable? Это, блядь, как волшебная палочка. Первый раз метод выполнится по-честному, сходет в репозиторий. А результат — хвать! — и схоронен в кэш под ключом #id. Второй раз, когда прилетит запрос с тем же айди, метод вообще не вызовется! Spring, хитрая жопа, посмотрит в кэш, достанет оттуда готовый объект и сразу его вернет. Скорость — ебать в сраку, просто космос!

А если товар обновили? Надо, чтобы в кэше тоже было свежо. Для этого другая аннотация — @CachePut.

    @CachePut(value = "products", key = "#product.id")
    public Product updateProduct(Product product) {
        // Обновляем БД и кэш одновременно
        return productRepository.save(product);
    }

Сохранил в базу — и сразу же, блядь, новую версию запихнул в кэш. Красота!

Ну а если товар удалили, то и из кэша его надо выковырять, а то будет висеть там призрак. @CacheEvict в помощь!

    @CacheEvict(value = "products", key = "#id")
    public void deleteProduct(Long id) {
        productRepository.deleteById(id);
    }

Удалил из базы — и кэш почистил. Порядок, блядь, должен быть во всём.

А под капотом-то можно что угодно поставить! Caffeine для скорости на одной ноде, Redis, если кэш на всех инстансах общий должен быть. Меняется это всё в конфиге, двумя строчками. Вот, смотри, для Caffeine:

spring:
  cache:
    type: caffeine
    caffeine:
      spec: maximumSize=500, expireAfterWrite=10m

Тут всё понятно: храним 500 записей максимум, и каждая живёт 10 минут после записи. Потом — нахуй, самоуничтожится.

Вот и вся философия, блядь. Не надо руками в каждом методе писать if (cache.contains(...)). Написал логику один раз правильно, развесил аннотации — и приложение сразу начинает работать в разы шустрее на повторяющихся запросах. А главное — если завтра начальство скажет «Хочу Redis вместо Caffeine», ты не будешь переписывать весь код, а поменяешь только настройки. Пиздато же!