Весенний бут Redis Кеш

Spring Boot Кэш Redis

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

Настройка проекта Spring Boot Redis

Мы воспользуемся инструментом Spring Initializr для быстрой настройки проекта. Мы будем использовать 3 зависимости, как показано ниже: Загрузите проект и разархивируйте его. Мы использовали зависимость от базы данных H2, так как будем использовать встроенную базу данных, которая теряет все данные после остановки приложения.

Spring Boot Redis Cache Maven Dependencies

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

<parent>
  <groupId>org.springframework.boot</groupId>
  <artifactId>spring-boot-starter-parent</artifactId>
  <version>1.5.9.RELEASE</version>
  <relativePath/> <!-- lookup parent from repository -->
</parent>
<properties>
  <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
  <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
  <java.version>1.8</java.version>
</properties>
<dependencies>
  <dependency>
     <groupId>org.springframework.boot</groupId>
     <artifactId>spring-boot-starter-data-redis</artifactId>
  </dependency>

  <dependency>
     <groupId>org.springframework.boot</groupId>
     <artifactId>spring-boot-starter-web</artifactId>
  </dependency>

  <dependency>
     <groupId>org.springframework.boot</groupId>
     <artifactId>spring-boot-starter-test</artifactId>
     <scope>test</scope>
  </dependency>

  <!-- for JPA support -->
  <dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-jpa</artifactId>
  </dependency>

  <!-- for embedded database support -->
  <dependency>
    <groupId>com.h2database</groupId>
    <artifactId>h2</artifactId>
    <scope>runtime</scope>
  </dependency>

</dependencies>

<build>
  <plugins>
     <plugin>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-maven-plugin</artifactId>
     </plugin>
  </plugins>
</build>

Убедитесь использовать стабильную версию Spring Boot из центрального репозитория Maven maven central.

Определение модели

Чтобы сохранить объект в базу данных Redis, мы определяем объект модели Person с базовыми полями:

package com.journaldev.rediscachedemo;

import javax.persistence.*;
import java.io.Serializable;

@Entity
public class User implements Serializable {

    private static final long serialVersionUID = 7156526077883281623L;

    @Id
    @SequenceGenerator(name = "SEQ_GEN", sequenceName = "SEQ_USER", allocationSize = 1)
    @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "SEQ_GEN")
    private Long id;
    private String name;
    private long followers;

    public User() {
    }

    public User(String name, long followers) {
        this.name = name;
        this.followers = followers;
    }

    //стандартные геттеры и сеттеры

    @Override
    public String toString() {
        return String.format("User{id=%d, name='%s', followers=%d}", id, name, followers);
    }
}

Это стандартный POJO с геттерами и сеттерами.

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

С Spring Boot и необходимой зависимостью, уже в работе с Maven, мы можем настроить локальный экземпляр Redis всего тремя строками в файле application.properties:

# Конфигурация Redis
spring.cache.type=redis
spring.redis.host=localhost
spring.redis.port=6379

Также используйте аннотацию @EnableCaching в основном классе Spring Boot:

package com.journaldev.rediscachedemo;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.CommandLineRunner;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cache.annotation.EnableCaching;

@SpringBootApplication
@EnableCaching
public class Application implements CommandLineRunner {

  private final Logger LOG = LoggerFactory.getLogger(getClass());
  private final UserRepository userRepository;

  @Autowired
  public Application(UserRepository userRepository) {
    this.userRepository = userRepository;
  }

  public static void main(String[] args) {
    SpringApplication.run(Application.class, args);
  }

  @Override
  public void run(String... strings) {
    //Заполнение встроенной базы данных здесь
    LOG.info("Saving users. Current user count is {}.", userRepository.count());
    User shubham = new User("Shubham", 2000);
    User pankaj = new User("Pankaj", 29000);
    User lewis = new User("Lewis", 550);

    userRepository.save(shubham);
    userRepository.save(pankaj);
    userRepository.save(lewis);
    LOG.info("Done saving users. Data: {}.", userRepository.findAll());
  }
}

Мы добавили CommandLineRunner, потому что хотим заполнить некоторые образцовые данные во встроенной базе данных H2.

Определение репозитория

Прежде чем мы покажем, как работает Redis, давайте определим репозиторий для функциональности, связанной с JPA:

package com.journaldev.rediscachedemo;

import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;

@Repository
public interface UserRepository extends JpaRepository { }

На данный момент у него нет вызовов методов, так как нам это не нужно.

Определение контроллера

Контроллеры – это место, где вызывается кэш Redis для действия. Фактически, это лучшее место для этого, потому что поскольку кэш непосредственно связан с ним, запрос даже не будет заходить в код сервиса, чтобы ждать кэшированных результатов. Вот каркас контроллера:

package com.journaldev.rediscachedemo;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.CachePut;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.web.bind.annotation.*;

@RestController
public class UserController {

  private final Logger LOG = LoggerFactory.getLogger(getClass());

  private final UserRepository userRepository;

  @Autowired
  public UserController(UserRepository userRepository) {
    this.userRepository = userRepository;
  }
   ...
}

Теперь, чтобы что-то поместить в кэш, мы используем аннотацию @Cacheable:

@Cacheable(value = "users", key = "#userId", unless = "#result.followers < 12000")
@RequestMapping(value = "/{userId}", method = RequestMethod.GET)
public User getUser(@PathVariable String userId) {
  LOG.info("Getting user with ID {}.", userId);
  return userRepository.findOne(Long.valueOf(userId));
}

В вышеуказанном сопоставлении метод getUser поместит человека в кэш с именем “users”, идентифицирует этого человека по ключу “userId” и будет хранить только пользователя с количеством подписчиков более 12000. Это гарантирует, что кэш заполняется пользователями, которые очень популярны и часто запрашиваются. Кроме того, мы специально добавили оператор журнала в вызов API. Давайте сделаем некоторые вызовы API из Postman в данный момент. Вот вызовы, которые мы сделали:

localhost:8090/1
localhost:8090/1
localhost:8090/2
localhost:8090/2

Если мы обратим внимание на журналы, они будут такими:

... : Getting user with ID 1.
... : Getting user with ID 1.
... : Getting user with ID 2.

Обратите внимание на что-то? Мы сделали четыре вызова API, но присутствовали только три записи в журнале. Это потому, что у пользователя с ID 2 есть 29000 подписчиков, и, таким образом, его данные были закешированы. Это означает, что при выполнении вызова API данные были возвращены из кеша, и для этого не было сделано вызова к базе данных!

Обновление кеша

Значения кеша также должны обновляться, когда обновляются значения их фактических объектов. Это можно сделать с использованием аннотации @CachePut:

@CachePut(value = "users", key = "#user.id")
@PutMapping("/update")
public User updatePersonByID(@RequestBody User user) {
  userRepository.save(user);
  return user;
}

С помощью этого человек снова идентифицируется по его ID и обновляется результатами.

Очистка кеша

Если некоторые данные должны быть удалены из фактической базы данных, нет смысла держать их в кеше. Мы можем очистить кеш, используя аннотацию @CacheEvict:

@CacheEvict(value = "users", allEntries=true)
@DeleteMapping("/{id}")
public void deleteUserByID(@PathVariable Long id) {
  LOG.info("deleting person with id {}", id);
  userRepository.delete(id);
}

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

Запуск приложения кеша Redis Spring Boot

Мы можем запустить это приложение просто с помощью одной команды:

mvn spring-boot:run

Ограничения кэша Redis

Хотя Redis очень быстрый, он всё ещё не имеет ограничений на хранение любого объема данных в 64-битной системе. Он может хранить только 3 ГБ данных в 32-битной системе. Больший объем доступной памяти может привести к увеличению попаданий в кэше, но это будет прекращаться, когда Redis займет слишком много памяти. Когда размер кэша достигает предела памяти, старые данные удаляются, чтобы освободить место для новых.

Резюме

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

Скачать проект Spring Boot Redis Cache

Source:
https://www.digitalocean.com/community/tutorials/spring-boot-redis-cache