Cache de Redis de Spring Boot
En esta publicación, configuraremos una aplicación de muestra de Spring Boot e integraremos con la Cache de Redis. Si bien Redis es una tienda de estructuras de datos en memoria de código abierto, utilizada como base de datos, caché y broker de mensajes, esta lección demostrará solo la integración de caché. Utilizaremos la herramienta Spring Initializr para configurar rápidamente el proyecto.
Configuración del Proyecto Spring Boot Redis
Utilizaremos la herramienta Spring Initializr para configurar rápidamente el proyecto. Utilizaremos 3 dependencias como se muestra a continuación: Descargue el proyecto y descomprímalo. Hemos utilizado la dependencia de la base de datos H2 ya que utilizaremos una base de datos incrustada que pierde todos los datos una vez que se detiene la aplicación.
Dependencias Maven para Spring Boot Redis Cache
Aunque ya completamos la configuración con la herramienta, si deseas configurarlo manualmente, utilizamos el sistema de construcción Maven para este proyecto y aquí están las dependencias que usamos:
<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>
Asegúrate de usar la versión estable de Spring Boot desde el repositorio central de Maven.
Definiendo el Modelo
Para guardar un objeto en la base de datos de Redis, definimos un objeto modelo Person con campos básicos:
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;
}
// getters y setters estándar
@Override
public String toString() {
return String.format("User{id=%d, name='%s', followers=%d}", id, name, followers);
}
}
Es un POJO estándar con getters y setters.
Configurando la Caché de Redis
Con Spring Boot y la dependencia requerida ya funcionando con Maven, podemos configurar una instancia local de Redis con solo tres líneas en nuestro archivo application.properties como:
# Configuración de Redis
spring.cache.type=redis
spring.redis.host=localhost
spring.redis.port=6379
También, utiliza la anotación @EnableCaching
en la clase principal de 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) {
// Poblando la base de datos incrustada aquí
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());
}
}
Hemos agregado un CommandLineRunner ya que queremos poblar algunos datos de muestra en la base de datos H2 incrustada.
Definición del Repositorio
Antes de mostrar cómo funciona Redis, simplemente definiremos un Repositorio para funcionalidades relacionadas con JPA:
package com.journaldev.rediscachedemo;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;
@Repository
public interface UserRepository extends JpaRepository { }
Actualmente no tiene llamadas de método ya que no las necesitamos.
Definición del Controlador
Los controladores son el lugar donde se llama a la caché de Redis para la acción. De hecho, este es el mejor lugar para hacerlo porque como la caché está directamente asociada, la solicitud ni siquiera tiene que entrar en el código de servicio para esperar los resultados en caché. Aquí está el esqueleto del controlador:
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;
}
...
}
Ahora, para poner algo en la caché, usamos la anotación @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));
}
En el mapeo anterior, el método getUser
colocará una persona en una caché llamada ‘usuarios’, identifica a esa persona por la clave ‘userId’ y solo almacenará un usuario con más de 12000 seguidores. Esto asegura que la caché esté poblada con usuarios que son muy populares y que a menudo se consultan. Además, hemos agregado intencionalmente una declaración de registro en la llamada a la API. Hagamos algunas llamadas a la API desde Postman en este momento. Estas son las llamadas que hicimos:
localhost:8090/1
localhost:8090/1
localhost:8090/2
localhost:8090/2
Si observamos los registros, estos serán:
... : Getting user with ID 1.
... : Getting user with ID 1.
... : Getting user with ID 2.
¿Notaste algo? Realizamos cuatro llamadas a la API pero solo hubo tres registros presentes. Esto se debe a que el Usuario con ID 2 tiene 29000 seguidores, por lo que sus datos fueron almacenados en caché. Esto significa que cuando se realizó una llamada a la API para él, los datos se devolvieron desde la caché y no se realizó ninguna llamada a la base de datos para esto.
Actualizando caché
Los valores de la caché también deben actualizarse cada vez que se actualizan los valores de sus objetos reales. Esto se puede hacer usando la anotación @CachePut:
@CachePut(value = "users", key = "#user.id")
@PutMapping("/update")
public User updatePersonByID(@RequestBody User user) {
userRepository.save(user);
return user;
}
Con esto, una persona es identificada nuevamente por su ID y se actualiza con los resultados.
Borrando caché
Si se va a eliminar algunos datos de la base de datos real, no tendría sentido mantenerlos en caché. Podemos borrar los datos de la caché usando la anotación @CacheEvict
:
@CacheEvict(value = "users", allEntries=true)
@DeleteMapping("/{id}")
public void deleteUserByID(@PathVariable Long id) {
LOG.info("deleting person with id {}", id);
userRepository.delete(id);
}
En el último mapeo, simplemente eliminamos las entradas de la caché y no hicimos nada más.
Ejecutando la aplicación de caché Redis de Spring Boot
Podemos ejecutar esta aplicación simplemente usando un solo comando:
mvn spring-boot:run
Límites de Caché de Redis
Aunque Redis es muy rápido, aún no tiene límites en el almacenamiento de cualquier cantidad de datos en un sistema de 64 bits. Solo puede almacenar 3 GB de datos en un sistema de 32 bits. Más memoria disponible puede resultar en una mayor proporción de aciertos, pero esto tenderá a cesar una vez que Redis ocupe demasiada memoria. Cuando el tamaño de la caché alcanza el límite de memoria, se eliminan los datos antiguos para dar paso a los nuevos.
Resumen
En esta lección, analizamos qué potencia nos proporciona Redis Cache con una interacción rápida de datos y cómo podemos integrarlo con Spring Boot con una configuración mínima y, sin embargo, poderosa. Siéntase libre de dejar comentarios abajo.
Source:
https://www.digitalocean.com/community/tutorials/spring-boot-redis-cache