Spring Boot con Redis: funcionalidad CRUD de HashOperations

    Introducci贸n

    REmote DIctionary Server (Redis) es un almac茅n de estructura de datos en memoria. Puede utilizarse como una base de datos simple, un intermediario de mensajes y para el almacenamiento en cach茅 gracias a su soporte para varias estructuras de datos.

    En este art铆culo, crearemos una aplicaci贸n CRUD simple e integraremos Redis con Spring Boot. Para lograr la funcionalidad CRUD, confiaremos en el HashOperations interfaz proporcionada por el Spring Data Redis proyecto.

    Redis

    Redis es un almac茅n de datos en memoria de c贸digo abierto escrito en C, lo que lo hace incre铆blemente r谩pido. Debido a sus operaciones de lectura / escritura m谩s r谩pidas, se usa com煤nmente para almacenar datos en cach茅. Los datos se almacenan en Redis en forma de pares clave-valor donde se usa una clave para extraer los valores.

    Redis tambi茅n puede conservar los datos en un disco, en lugar de mantenerlos en la memoria, mediante “instant谩neas”, copiando su almac茅n de datos en la memoria a intervalos regulares.

    Prerrequisitos

    Instalaci贸n de Redis

    Redis se puede instalar f谩cilmente en Linux y macOS. Sin embargo, Windows requiere un poco de pirater铆a. Instalaremos Redis en una instancia AWS EC2 que ejecute Ubuntu 18.04 LTS:

    $ sudo apt install redis-server
    

    macOS, puedes instalarlo a trav茅s de brew:

    $ brew install redis
    

    Despu茅s de instalar con 茅xito el redis-server paquete, verifiquemos el estado del proceso de Redis para verificar la instalaci贸n:

    $ systemctl status redis
    

    El resultado muestra el estado del redis-server, la direcci贸n de enlace y el puerto en el que redis-server est谩 escuchando en:

    鈼 redis-server.service - Advanced key-value store
       Loaded: loaded (/lib/systemd/system/redis-server.service; enabled; vendor preset: enabled)`
       Active: active (running) since Tue 2020-03-10 10:06:30 UTC; 3min 2s ago
         Docs: http://redis.io/documentation,
               man:redis-server(1)
     Main PID: 2227 (redis-server)
        Tasks: 4 (limit: 1152)
       CGroup: /system.slice/redis-server.service
               鈹斺攢2227 /usr/bin/redis-server 127.0.0.1:6379
    

    De forma predeterminada, la configuraci贸n de Redis estar谩 disponible en la /etc/redis/redis.conf archivo.

    Habilitar la conexi贸n remota a Redis

    De forma predeterminada, solo se puede acceder a Redis desde localhost. Para habilitar la conexi贸n remota a nuestro servidor Redis, actualice la direcci贸n de enlace en la configuraci贸n de Redis a 0.0.0.0:

    bind 0.0.0.0 ::1
    

    Una vez actualizado, rein铆cielo:

    $ systemctl restart redis
    

    Configuraci贸n de Spring Boot

    La forma m谩s f谩cil de comenzar con una aplicaci贸n Spring Boot en blanco es usar Spring Initializr:

    Alternativamente, tambi茅n puede utilizar el Spring Boot CLI para arrancar la aplicaci贸n:

    $ spring init --dependencies=spring-boot-starter-data-redis redis-spring-boot-demo
    

    Empezamos con el spring-boot-starter-data-redis dependencia ya que incluye spring-data-redis, spring-boot-starter y lettuce-core.

    Si ya tiene una aplicaci贸n Maven / Spring, agregue la dependencia a su pom.xml archivo:

    <dependency>
    	<groupId>org.springframework.boot</groupId>
    	<artifactId>spring-boot-starter-data-redis</artifactId>
    	<version>${version}</version>
    </dependency>
    

    O si est谩 usando Gradle:

    compile group: 'org.springframework.data', name: 'spring-data-redis', version: '${version}'
    

    Conexi贸n al servidor Redis

    Como siempre, cuando trabajamos con servicios como Redis, queremos conectar nuestra aplicaci贸n al servicio. Hay disponibles varios conectores Redis basados 鈥嬧媏n Java: Jedis y Lechuga son dos opciones populares.

    Conectando con Jedis

    Para usar Jedis, tendremos que agregarlo a nuestro pom.xml archivo:

    <dependency>
    	<groupId>redis.clients</groupId>
    	<artifactId>jedis</artifactId>
    	<version>${version}</version>
    </dependency>
    

    O si est谩 usando Gradle:

    compile group: 'redis.clients', name: 'jedis', version: '${version}'
    

    Una vez que las dependencias est谩n en su lugar, necesitamos configurar el JedisConnectionFactory:

    @Configuration
    public class Config {
        @Bean
        public JedisConnectionFactory redisConnectionFactory() {
            JedisConnectionFactory jedisConnectionFactory = new JedisConnectionFactory();
            jedisConnectionFactory.setHostName("your_host_name_or_ip");
            jedisConnectionFactory.setPort(6379);
            jedisConnectionFactory.afterPropertiesSet();
            return jedisConnectionFactory;
        }
    }
    

    No hace falta decir que esta configuraci贸n se realiza en un @Configuration clase. Si desea leer m谩s sobre las anotaciones principales de Spring Framework, 隆lo tenemos cubierto!

    Conectando con la lechuga

    La lechuga es Netty-conector Redis de c贸digo abierto y basado en el paquete con la dependencia de inicio. La configuraci贸n de una f谩brica de conexiones Lettuce es pr谩cticamente la misma que la de Jedis:

    @Configuration
    public class Config {
        @Bean 
        public LettuceConnectionFactory redisConnectionFactory() {
            LettuceConnectionFactory lcf = new LettuceConnectionFactory();
            lcf.setHostName("your_host_name_or_ip");
            lcf.setPort(6379);		
            lcf.afterPropertiesSet();
            return lcf;
        }
    }
    

    Aunque su configuraci贸n es pr谩cticamente la misma, su uso es diferente. Lettuce permite operaciones asincr贸nicas y es seguro para subprocesos, a diferencia de Jedis, por ejemplo.

    RedisTemplate

    RedisTemplate es una clase de entrada proporcionada por Spring Data a trav茅s de la cual interactuamos con el servidor Redis.

    Pasaremos un RedisConnectionFactory instancia a la RedisTemplate para establecer una conexi贸n:

    public static RedisTemplate<String, User> redisTemplate() {
        RedisTemplate<String, User> redisTemplate = new RedisTemplate<String ,User>();
        redisTemplate.setConnectionFactory(redisConnectionFactory());
        redisTemplate.afterPropertiesSet();
        return redisTemplate;
    }
    

    Una vez establecido, RedisTemplate se convierte en la principal abstracci贸n de las operaciones de Redis que podemos controlar. Tambi茅n se encarga de la serializaci贸n y deserializaci贸n de objetos en matrices de bytes.

    Por defecto, RedisTemplate usa el JdkSerializationRedisSerializer serializar y deserializar objetos.

    El mecanismo de serializaci贸n de RedisTemplate puede cambiarse, y Redis ofrece varios serializadores en el org.springframework.data.redis.serializer paquete.

    StringRedisTemplate es una extensi贸n de RedisTemplate centrado en pares clave-valor basados 鈥嬧媏n cadenas, por ejemplo.

    Para admitir varias operaciones en diferentes tipos de datos, RedisTemplate proporciona clases de operaci贸n como ValueOperations, ListOperations, SetOperations, HashOperations, StreamOperationsetc.

    Para operaciones relacionadas con hash, que usaremos para almacenar datos en nuestro servidor Redis, usaremos el HashOperations clase.

    HashOperations

    Redis Hashes puede contener un n n煤mero de pares clave-valor y est谩n dise帽ados para usar menos memoria, lo que lo convierte en una excelente manera de almacenar objetos en la memoria. A trav茅s de HashOperations ayudante, podemos manipularlos.

    Para usar cualquiera de estos, empaquetamos las operaciones hash devueltas del RedisTemplate instancia en el HashOperations interfaz:

    HashOperations hashOperations = redisTemplate.opsForHash();
    

    Estas operaciones incluyen operaciones b谩sicas de mapas hash como put(), get(), entries(), etc:

    // Sets user object in USER hashmap at userId key
    hashOperations.put("USER", user.getUserId(), user);
    
    // Get value of USER hashmap at userId key
    hashOperations.get("USER", userId);
    
    // Get all hashes in USER hashmap
    hashOperations.entries("USER");
    
    // Delete the hashkey userId from USER hashmap
    hashOperations.delete("USER", userId);
    

    Definici贸n de un repositorio de usuarios

    Ahora sigamos adelante y creemos un repositorio de usuarios que realmente manejar谩 las operaciones CRUD:

    @Repository
    public class UserRepository {
        private HashOperations hashOperations;
        public UserRepository(RedisTemplate redisTemplate) {
            this.hashOperations = redisTemplate.opsForHash();
        }
    }
    

    Por el contrario, en un repositorio t铆pico, el HashOperations ser铆a algo as铆 como un SessionFactory. Con Redis, tambi茅n puede crear un repositorio ampliando la CrudRepository interfaz y configurar una conexi贸n Jedis en un @Bean.

    En el constructor, pasamos nuestro redisTemplate, que debe configurarse con una f谩brica de conexiones de Redis.

    Ahora, para poner una entrada, usar铆amos:

    hashOperations.put("USER", hashKey, value);
    

    Una sola tecla, como la USER puede tener m煤ltiples hashKey:value pares. Cada value se puede acceder a trav茅s de hashKeys para una clave determinada.

    O para obtener una entrada, usar铆amos:

    value = hashOperations.get("USER", hashKey);
    

    Definamos el User:

    public class User {
        private int userId;
        private String name;
        
        // Constructor, getters and setters
    }
    

    Con eso en mente, implementemos el resto del repositorio:

    @Repository
    public class UserRepository {
        
        final Logger logger = LoggerFactory.getLogger(UserRepository.class);
    	private HashOperations hashOperations;
    	
    	public UserRepository(RedisTemplate redisTemplate) {
    		this.hashOperations = redisTemplate.opsForHash();
    	}
    	
    	public void create(User user) {
    		hashOperations.put("USER", user.getUserId(), user);
            logger.info(String.format("User with ID %s saved", user.getUserId()));
    	}
    	
    	public User get(String userId) {
    		return (User) hashOperations.get("USER", userId);
    	}
    
    	public Map<String, User> getAll(){
    		return hashOperations.entries("USER");
    	}
    	
    	public void update(User user) {
    		hashOperations.put("USER", user.getUserId(), user);
            logger.info(String.format("User with ID %s updated", user.getUserId()));
    	}
    	
    	public void delete(String userId) {
    		hashOperations.delete("USER", userId);
            logger.info(String.format("User with ID %s deleted", userId));
    	}
    }
    

    Ahora para probar la aplicaci贸n, usemos nuestro userRepository:

    UserRepository userRepository = new UserRepository(redisTemplate());
    
    userRepository.create(new User("1", "username", "emailid"));
    User user = userRepository.get("1");
    userRepository.update(user);
    userRepository.delete(user.getUserId());
    

    Ejecutar este fragmento de c贸digo producir谩:

    2020-03-30 11:34:11.260  INFO 8772 --- [           main] c.h.redistutorial.UserRepository       : User with ID 1 saved
    2020-03-30 11:34:11.260  INFO 8772 --- [           main] c.h.redistutorial.UserRepository       : User with ID 1 updated
    2020-03-30 11:34:11.260  INFO 8772 --- [           main] c.h.redistutorial.UserRepository       : User with ID 1 deleted
    

    Usemos un cliente de Redis para ver los datos que se insertan, actualizan y eliminan.

    • Creando un usuario:
    • Actualizaci贸n de un usuario:
    • Eliminar un usuario:

    Conclusi贸n

    Spring Boot es cada vez m谩s preferido por los desarrolladores de Java / Spring porque es liviano y f谩cil de usar. Simplifica enormemente el proceso de arranque de aplicaciones y le ayuda a concentrarse en la l贸gica empresarial real en lugar de conectar las cosas.

    Redis, por otro lado, es una base de datos en memoria extremadamente popular que la convierte en un gran compa帽ero para los microservicios.

    Redis se usa a menudo para la administraci贸n de cach茅 por microservicios para reducir la cantidad de llamadas de base de datos al servidor. En este nuevo mundo de sistemas de cobro de pago por uso, esto puede reducir efectivamente los costos operativos para empresas y empresas.

    Etiquetas:

    Deja una respuesta

    Tu direcci贸n de correo electr贸nico no ser谩 publicada. Los campos obligatorios est谩n marcados con *