Translate

Mostrando las entradas con la etiqueta Redis. Mostrar todas las entradas
Mostrando las entradas con la etiqueta Redis. Mostrar todas las entradas

viernes, 16 de agosto de 2024

Scripts de Lua en Redis


Redis, conocido por ser un sistema de almacenamiento de datos en memoria altamente rápido, no tiene soporte directo para procedimientos almacenados o funciones como los sistemas de bases de datos relacionales tradicionales. Sin embargo, Redis ofrece características que permiten realizar operaciones complejas y reutilizables de manera similar a los procedimientos almacenados y funciones, principalmente a través de scripts en Lua.

Lua es un lenguaje de scripting ligero y potente, y Redis permite la ejecución de scripts Lua en su entorno. Esto brinda la posibilidad de realizar operaciones más complejas que las que se pueden lograr con los comandos básicos de Redis.


Por qué usar Lua en Redis: 

  • Atomicidad: Los scripts Lua se ejecutan de manera atómica en Redis, lo que significa que ninguna otra operación puede interferir con la ejecución del script.
  • Reutilización: Puedes almacenar y reutilizar scripts Lua para realizar operaciones complejas, lo que es análogo a los procedimientos almacenados.
  • Flexibilidad: Lua te permite hacer uso de la lógica de programación, como condicionales y bucles, directamente dentro de Redis.


Supongamos que queremos implementar un procedimiento que incremente el valor de una clave solo si la clave existe y su valor es mayor que un umbral dado. Este es un típico ejemplo donde un procedimiento almacenado sería útil en un sistema de bases de datos relacional.


-- Script Lua para incrementar un valor si es mayor que un umbral

local current = redis.call('GET', KEYS[1])

if current and tonumber(current) > tonumber(ARGV[1]) then

    return redis.call('INCRBY', KEYS[1], ARGV[2])

else

    return nil

end


Para ejecutar este script en Redis, puedes usar el comando `EVAL`:


EVAL "local current = redis.call('GET', KEYS[1])

if current and tonumber(current) > tonumber(ARGV[1]) then

    return redis.call('INCRBY', KEYS[1], ARGV[2])

else

    return nil

end" 1 mykey 10 5


Este comando recibe los siguientes parametros :

  • 1 indica el número de claves (`mykey`) que el script recibirá.
  • mykey es la clave en Redis que el script verificará y posiblemente incrementará.
  • 10 es el umbral; si el valor actual de `mykey` es mayor que este valor, se incrementará.
  • 5 es la cantidad por la cual se incrementará el valor de `mykey` si la condición se cumple.


Aunque Redis no tiene una noción de funciones al estilo SQL, puedes pensar en los scripts Lua como funciones reutilizables. Si bien Redis no permite definir funciones Lua en el mismo sentido que los procedimientos almacenados en SQL, puedes almacenar el script en Redis y llamarlo repetidamente.


Para almacenar un script:


SCRIPT LOAD "local current = redis.call('GET', KEYS[1])

if current and tonumber(current) > tonumber(ARGV[1]) then

    return redis.call('INCRBY', KEYS[1], ARGV[2])

else

    return nil

end


Esto te devolverá un `sha1` hash del script, que puedes usar para invocarlo nuevamente:


EVALSHA <sha1> 1 mykey 10 5


Mientras que Redis no soporta procedimientos almacenados y funciones en el sentido tradicional de bases de datos relacionales, su capacidad para ejecutar scripts Lua te permite realizar operaciones avanzadas y reutilizables de manera similar. Esta funcionalidad es extremadamente útil cuando necesitas lógica compleja o atomicidad en tus operaciones con Redis.

sábado, 9 de julio de 2022

Hacer un test de integración de un dao que guarda en Redis con Testcontainers y Spring boot


Me quedo relargo el titulo, pero la idea sería:

Tenemos una aplicación de spring boot y spring data que guarda información en Redis con un Dao y queremos probar este dao, ¿como lo hacemos?. Podemos usar testcontainers. 

Testcontainers es un framework que levanta una imagen de docker para que diferentes tecnologías esten accesibles para nuestros tests. 

Para utilizarlo debemos agregar esta dependencia en gradle o maven :


testImplementation "org.testcontainers:testcontainers:1.17.2"


Y en este ejemplo vamos a utilizar kotlin, pero funciona tambien con Java: 


@RunWith(SpringJUnit4ClassRunner::class)

@SpringBootTest(classes = [Application::class])

class EjemploRepositoryTest {


    @Autowired

    lateinit var ejemploRepository: EjemploRepository


    companion object {

        

        init {

            val redis : GenericContainer<Nothing>  = GenericContainer<Nothing>(DockerImageName.parse("redis:5.0.3-alpine"))

                .withExposedPorts(6379)


            redis.start()


            System.setProperty("redis.host", "${redis.host}")

            System.setProperty("redis.port", "${redis.firstMappedPort}")

        }

    }


    @Test

    fun `save and find all ejemplos`() {

        val count = ejemploRepository.findAll().count()

        val ejemplo = crearUnEjemplo() //este metodo te crea un ejemplo :D


        ejemploRepository.save(ejemplo)

        val ejemplos = ejemplo.findAll()


        Assert.assertNotNull(ejemplos)

        Assert.assertEquals(count + 1, ejemplos.count())

    }


}

En el código anterior falta el metodo crear ejemplo que va a crear el objeto para probar, no lo agrego porque no lo veo necesario. Por supuesto, el objeto ejemplo debe seguir con las notaciones de Spring data. 

Y listo! 

miércoles, 1 de junio de 2022

Cache con Redis y Spring boot


Vamos ha hacer una pequeña cache para unos servicios en spring boot. 

Primero es necesario tener instalado Redis, y si ...

Luego agregamos esta dependencia a nuestro proyecto (uso gradle) : 

implementation("org.springframework.boot:spring-boot-starter-cache")

implementation("org.springframework.boot:spring-boot-starter-data-redis")


Luego configuramos en nuestro cache con esta clase : 

 package com.uap.demo.config

import org.springframework.context.annotation.Bean
import org.springframework.context.annotation.Configuration
import org.springframework.data.redis.cache.RedisCacheConfiguration
import org.springframework.data.redis.serializer.GenericJackson2JsonRedisSerializer
import org.springframework.data.redis.serializer.RedisSerializationContext.SerializationPair
import java.time.Duration

@Configuration
class CacheConfig {

    @Bean
    fun cacheConfiguration(): RedisCacheConfiguration? {
        return RedisCacheConfiguration.defaultCacheConfig()
            .entryTtl(Duration.ofMinutes(60))
            .disableCachingNullValues()
            .serializeValuesWith(SerializationPair.fromSerializer(GenericJackson2JsonRedisSerializer()))
    }
}

Yo le puse 60 minutos de vida a mis datos dado que no cambian tan frecuente. 

Ahora en el Application agregamos @EnableCaching, algo así : 

@SpringBootApplication
@EnableCaching
class DemoApplication

fun main(args: Array<String>) {
runApplication<DemoApplication>(*args)
}

Por ultimo a nuestro servicio le decimos que vamos a cachear los datos, en este ejemplo tengo un servicio X : 

@Service
class XServiceImpl : XService {

    @Cacheable(value = ["xxxxx"])
    override fun x(parametro: String): List<String> {
          ...
    }
}

Lo que va a ocurrir es que cuando llamemos al servicio con un parametro, se va generar una entrada en Redis, y la próxima vez que llamemos este servicio usará la cache. 

Y listo!!! 

Another Redis Desktop Manager


Haciendo unas cosas con Redis me encontré con esta aplicación y me pareció muy buena. 

Un administrador de escritorio redis rápido y estable, compatible con Linux, Windows, Mac.

En Ubuntu esta en el store, así que lo instale totalmente de forma automática. 

Dejo unos screenshots : 





Dejo link : 

https://github.com/qishibo/AnotherRedisDesktopManager

lunes, 2 de septiembre de 2013

DB-Engines Ranking

Existe un ranking de base de datos, en realidad de almacenes de datos porque hay del tradicional entidad-relación al NoSQL. Bien no se de donde toman los datos pero se ve coherente.

Dejo link:
http://db-engines.com/en/ranking

miércoles, 24 de julio de 2013

NoSQL Database Adoption Trends

InfoQ se le ocurrió una gran idea hacer una encuesta sobre bases de datos NoSQL y ya tiempo ha pasado desde que las bases NoSQL se convirtieron de una moda a algo de todos los días. InfoQ organizo la encuesta como una matriz de 2 dimensiones: propósito y adopción. Eso esta bueno, una base puede ser fácil de adoptar pero la mejora no es significativa.

Por ahorra va ganando MongoDB en adopción y Redis en propósito.

A votar!

 http://www.infoq.com/research/nosql-databases?utm_source=infoqEmail&utm_medium=WeeklyNL_ResearchContent&utm_campaign=072313news


jueves, 20 de diciembre de 2012

7 base de datos en 7 días



Se acuerdan que hable de un libro muy bueno llamado 7 lenguajes en 7 días, bueno Eric Redmond y Jim R. Wilson lanzaron un nuevo libro llamado 7 base de datos en 7 días. En el recorre base de datos relacionales y NoSQL. Las bases que se muestran son Redis, Neo4J, CouchDB, MongoDB, HBase, Riak, y Postgres. La idea es no saber todas, pero si sus particularidades y porque elegir una o la otra.

Dejo el link:
http://pragprog.com/book/rwdata/seven-databases-in-seven-weeks