Spring Boot con Redis: operaciones de canalizaci贸n

     

    Introducci贸n

    Redis es un almac茅n de datos en memoria, que se puede utilizar como base de datos NoSQL, cach茅 o como un intermediario de mensajes t铆pico. Est谩 escrito en ANSI C, que se compila en un c贸digo de m谩quina significativamente eficiente y su capacidad para almacenar datos como pares clave-valor hace que el almacenamiento en cach茅 en memoria sea un caso de uso atractivo para Redis, adem谩s de conservar los datos en un disco.

    En este art铆culo, usaremos Pipelining para permitir que una aplicaci贸n Spring Boot env铆e m煤ltiples solicitudes al servidor Redis, de una manera sin bloqueo.

    Caso de uso de canalizaci贸n en Redis

    Redis se basa en una arquitectura Cliente / Servidor (Solicitud / Respuesta). En estas arquitecturas, un cliente normalmente env铆a una consulta o solicitud al servidor y espera una respuesta. Por lo general, esto se hace de forma de bloqueo de modo que no se pueda enviar una nueva solicitud hasta que se env铆e la respuesta de la 煤ltima:

    Client: <command 1>
    Server: Response for <command 1>
    Client: <command 2>
    Server: Response for <command 2>
    Client: <command 3>
    Server: Response for <command 3>
    

    Esto puede conducir a ineficiencias masivas, con una alta latencia entre recibir comandos y procesarlos.

    La canalizaci贸n nos permite enviar m煤ltiples comandos, como una sola operaci贸n por parte del cliente, sin esperar la respuesta del servidor entre cada comando. Luego, todas las respuestas se leen juntas en su lugar:

    Client: <command 1>
    Client: <command 2>
    Client: <command 3>
    Server: Response for <command 1>
    Server: Response for <command 2>
    Server: Response for <command 3>
    

    Dado que el cliente no espera la respuesta del servidor antes de emitir otro comando, se reduce la latencia, lo que a su vez mejora el rendimiento de la aplicaci贸n.

    Nota: Los comandos aqu铆 se colocan en una cola. Esta cola debe tener un tama帽o razonable. Si est谩 tratando con decenas de miles de comandos, es mejor enviarlos y procesarlos en lotes, no sea que los beneficios de la canalizaci贸n se vuelvan redundantes.

    Implementaci贸n

    Sigamos adelante y creemos una peque帽a aplicaci贸n Spring Boot que funcione con Redis y canalice m煤ltiples comandos. Esto se hace m谩s f谩cil con la ayuda del Spring Data Redis proyecto.

    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}'
    

    Tambi茅n usaremos Jedis como cliente de conexi贸n, en lugar de Lettuce:

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

    Configuraci贸n de Redis

    Alojaremos Redis en Scalegrid, que proporciona una cuenta de prueba gratuita para alojar una instancia del servidor Redis. Alternativamente, puede descargar el servidor y al贸jelo en su propia computadora en Linux y MacOS. Windows requiere un poco de pirater铆a y es complicado de configurar.

    Vamos a configurar el JedisConnectionFactory para que nuestra aplicaci贸n pueda conectarse a la instancia del servidor Redis. En tus @Configuration clase, anote lo adecuado @Bean:

    @Configuration
    public class Config {
        @Bean
        public JedisConnectionFactory redisConnectionFactory() {
            JedisConnectionFactory jedisConnectionFactory = new JedisConnectionFactory();
            jedisConnectionFactory.setHostName("<server-hostname-here>");
            jedisConnectionFactory.setPort(6379);
            jedisConnectionFactory.setPassword("<server-password-here>");
            jedisConnectionFactory.afterPropertiesSet();
            return jedisConnectionFactory;
        }
    }
    

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

    Le pasaremos nuestra f谩brica de conexiones configurada:

    @Bean
    public RedisTemplate<String, String> redisTemplate() {
        RedisTemplate<String, String> redisTemplate = new RedisTemplate<>();
        redisTemplate.setConnectionFactory(redisConnectionFactory());
        redisTemplate.setDefaultSerializer(RedisSerializer.string());
        redisTemplate.afterPropertiesSet();
        return redisTemplate;
    }
    

    Hemos configurado el serializador predeterminado para almacenar claves y valores como String. Alternativamente, puede definir su propio serializador personalizado.

    Canalizaci贸n con RedisTemplate

    Agreguemos algunos elementos de una lista al servidor Redis. Haremos esto sin canalizar, usando el RedisTemplate. Espec铆ficamente, usaremos el ListOperations interfaz, adquirida de opsForList():

    List<String> values = Arrays.asList("value-1", "value-2", "value-3", "value-4", "value-5");
    redisTemplate.opsForList().leftPushAll("pipeline-list", values);
    

    Ejecutar este c贸digo resultar谩 en:

    Ahora, eliminemos estos. Imaginando que esta puede ser una operaci贸n costosa, canalizaremos cada rPop() comando para que se env铆en juntos y que los resultados se sincronicen con todos los elementos que se eliminan. Luego, recibiremos estos resultados. Para canalizar comandos, usamos el executedPipeline() m茅todo.

    Acepta un RedisCallback o SessionCallback que le proporcionamos. los executedPipeline() El m茅todo devuelve los resultados que luego podemos capturar y revisar. Si no es necesario y solo desea ejecutar los comandos, puede usar el execute() m茅todo y pasar true como el pipeline argumento en su lugar:

    List<Object> results = redisTemplate.executePipelined(new RedisCallback<Object>() {
        public Object doInRedis(RedisConnection connection) throws DataAccessException {
            for(int i = 0; i < 5; i++) {
                connection.rPop("pipeline-list".getBytes());
            }
        return null;
         }
    });
    return results;
    

    los executePipelined() m茅todo aceptado un new RedisCallback(), en el que usamos el doInRedis() m茅todo para especificar lo que nos gustar铆a hacer.

    Espec铆ficamente, hemos ejecutado el rPop() m茅todo 5 veces, eliminando los 5 elementos de lista que hemos insertado de antemano.

    Una vez que se han ejecutado los cinco comandos, los elementos se eliminan de la lista y se devuelven; los resultados se empaquetan en el results lista:

    Conclusi贸n

    El caso de uso m谩s popular de Redis es como almac茅n de cach茅. Sin embargo, tambi茅n se puede utilizar como base de datos o como intermediario de mensajes.

    Redis nos permite incrementar el rendimiento de las aplicaciones, minimizando las llamadas a la capa de base de datos. Su soporte para canalizaci贸n permite que se env铆en m煤ltiples comandos al servidor en una sola operaci贸n de escritura, reduciendo as铆 el tiempo de ida y vuelta hacia y desde el servidor.

    En este art铆culo, hemos canalizado varios comandos utilizando el RedisTemplate API y verific贸 los resultados.

    Etiquetas:

    Deja una respuesta

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