Кэширование Redis для максимальной производительности в Spring Boot и Java

1. Вводная информация по кэшированию и Redis

Кэширование  —  это метод хранения и повторного использования результатов высокозатратных операций для повышения производительности и снижения нагрузки на базовые системы. Он предполагает сохранение результатов операции во временном хранилище, называемом кэшем, а затем извлечение результатов из кэша вместо повторного выполнения операции при тех же входных данных.

Redis  —  это хранилище структур данных с открытым исходным кодом, которое основано на архитектуре in-memory. Его можно использовать в качестве базы данных, кэша и брокера сообщений. Оно обладает высокой производительностью и поддерживает широкий спектр структур данных, таких как строки, хэши, списки, множества и другие.

2. Настройка приложения Spring Boot

Для начала создайте новое приложение Spring Boot с помощью Spring Initializr. Добавьте следующие зависимости:

  • Web;
  • JPA;
  • Lombok;
  • Redis.

Вы можете создать проект и импортировать его в любимую IDE.

3. Настройка кэша Redis

Прежде чем использовать Redis в качестве кэша в приложении, его нужно настроить. Сначала добавьте следующие свойства в файл application.properties:

spring.redis.host=localhost
spring.redis.port=6379

Далее создайте класс конфигурации RedisCacheConfig:

@Configuration
@EnableCaching
public class RedisCacheConfig extends CachingConfigurerSupport {
@Value("${spring.redis.host}")
private String redisHost;
@Value("${spring.redis.port}")
private int redisPort;
@Bean
public JedisConnectionFactory jedisConnectionFactory() {
return new JedisConnectionFactory(new RedisStandaloneConfiguration(redisHost, redisPort));
}
@Bean
public RedisCacheManager cacheManager() {
return RedisCacheManager.builder(jedisConnectionFactory()).build();
}
}

Этот класс включает поддержку кэширования и настраивает бины (объекты) JedisConnectionFactory и RedisCacheManager.

4. Реализация сервисов с возможностью кэширования

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

Сначала создадим сущность User:

@Entity
@Data
@NoArgsConstructor
@AllArgsConstructor
public class User {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@Column(nullable = false)
private String name;
@Column(nullable = false)
private String email;
}

Теперь создадим интерфейс UserRepository:

public interface UserRepository extends JpaRepository<User, Long> {}

Далее создаем UserService:

@Service
public class UserService {
private final UserRepository userRepository;
public UserService(UserRepository userRepository) {
this.userRepository = userRepository;
}
@Cacheable(value = "users", key = "#id")
public User findById(Long id) {
return userRepository.findById(id).orElseThrow(() -> new IllegalArgumentException("User not found"));
}
}

Аннотация @Cacheable указывает на то, что результат метода findById должен быть кэширован. Атрибут value определяет имя кэша, а атрибут key  —  ключ кэша.

5. Способы вытеснения кэша

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

Обновите класс UserService, чтобы добавить методы для создания и обновления пользователей:

@Service
public class UserService {
private final UserRepository userRepository;
public UserService(UserRepository userRepository) {
this.userRepository = userRepository;
}
@Cacheable(value = "users", key = "#id")
public User findById(Long id) {
return userRepository.findById(id).orElseThrow(() -> new IllegalArgumentException("User not found"));
}
@CacheEvict(value = "users", key = "#user.id")
public User save(User user) {
return userRepository.save(user);
}
@CacheEvict(value = "users", key = "#user.id")
public User update(User user) {
findById(user.getId()); // Ensure the user exists
return userRepository.save(user);
}
@CacheEvict(value = "users", allEntries = true)
public void deleteById(Long id) {
userRepository.deleteById(id);
}
}

Аннотация @CacheEvict удаляет указанную запись кэша после выполнения метода. В нашем случае мы удаляем кэш при создании, обновлении и удалении пользователя.

6. Тестирование производительности

Теперь, когда мы внедрили кэширование, протестируем производительность. Создадим простой REST-контроллер и измерим время отклика с кэшированием и без него.

Создайте класс UserController:

@RestController
@RequestMapping("/api/users")
public class UserController {
private final UserService userService;
public UserController(UserService userService) {
this.userService = userService;
}
@GetMapping("/{id}")
public ResponseEntity<User> getUser(@PathVariable Long id) {
return ResponseEntity.ok(userService.findById(id));
}
}

Для измерения времени ответа можно использовать такие инструменты, как Apache JMeter, Postman и curl. Выполните несколько запросов, чтобы увидеть эффект от кэширования.

Заключение

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

Тщательно продумайте стратегию кэширования и политику вытеснения кэша, так как неправильные действия могут привести к устареванию данных и неожиданным результатам.

Читайте также:

Читайте нас в TelegramVK и Дзен


Перевод статьи Abhishek Ranjan: Leveraging Redis Caching for Maximum Performance with Spring Boot and Java

Предыдущая статьяНаписание консольных скриптов: Bash против Python
Следующая статьяДоступная и масштабируемая 3-уровневая архитектура AWS