Redis
Propuesta didáctica¶
Seguimos trabajando el siguiente resultado de aprendizaje (RA):
- RA7: Gestiona la información almacenada en bases de datos no relacionales, evaluando y utilizando las posibilidades que proporciona el sistema gestor.
Criterios de evaluación¶
- CE7c: Se han identificado los elementos utilizados en estas bases de datos.
- CE7d: Se han identificado distintas formas de gestión de la información según el tipo de base de datos no relacionales.
- CE7e: Se han utilizado las herramientas del sistema gestor para la gestión de la información almacenada.
Contenidos¶
Bases de datos no relacionales:
- Elementos de las bases de datos no relacionales.
- Sistemas gestores de bases de datos no relacionales.
- Herramientas de los sistemas gestores de bases de datos no relacionales para la gestión de la información almacenada.
Cuestionario inicial
- ¿Qué es Redis y cuáles son sus principales características como base de datos NoSQL?
- ¿Cuáles son las ventajas y desventajas de utilizar Redis como sistema de almacenamiento en memoria frente a otros sistemas de almacenamiento persistente?
- ¿Cómo se diferencian las bases de datos clave-valor de las bases de datos relacionales tradicionales?
- ¿Qué estructuras de datos admite Redis y cómo se utilizan en la gestión de información?
- ¿Cómo se implementan las operaciones CRUD?
- ¿Qué son los espacios de nombres y cuál es su propósito en la organización de claves?
- ¿Cómo se maneja la expiración de claves y qué comandos se utilizan para ello?
- ¿Cómo se implementan para garantizar la atomicidad de las operaciones?
- ¿Cómo se pueden representar y manipular estructuras de datos complejas, como JSON, dentro de Redis?
Programación de Aula (5h)¶
Seguimos con la penúltima unidad, y tras haber introducido los conceptos y elementos de los sistemas NoSQL, vamos a profundizar en el manejo de Redis, conociendo cómo funciona una solución clave-valor, con una duración estimada de 5 horas:
Sesión | Contenidos | Actividades | Criterios trabajados |
---|---|---|---|
5 | Redis. CRUD | AC1207 | CE7c, CE7d, CE7e |
6 | Listas | AC1209 | CE7c, CE7d, CE7e |
7 | Conjuntos | AC1211 | CE7c, CE7d, CE7e |
8 | JSON | ||
9 | Mensajería |
Redis¶

Redis es una base de datos NoSQL open source en memoria, con un modelo de datos de clave-valor, que permite el cacheo de los datos y funcionar como un broker de mensajería. Soporta estructuras de datos como cadenas, hash, listas, conjuntos, conjuntos ordenados con consultas por rango, así como otras estructuras más específicas como mapas de bit, consultas radius, índices geospaciales, etc...
El nombre Redis proviene de las iniciales de Remote Dictionary Server (servidor de diccionario remoto), un tipo de servidor apto como memoria rápida para datos, permitiendo su uso como una base de datos en memoria y como de clave-valor.
También se ofrece como una opción de pago mediante Redis Lab, ofreciéndola como una solución gestionada donde no tenemos que preocuparnos de la infraestructura.
Características¶
Redis almacena los datos como pares clave-valor, donde:
- Cada clave (key) es un identificador único (similar a una clave primaria en SQL)
- Cada valor (value) puede ser de diferente tipos (número, cadena, lista, hash, etc...)
Este modelo es fundamentalmente diferente del modelo relacional:
Característica | Redis (clave-valor) | SQL (relacional) |
---|---|---|
Estructura | Plana, no relacional | Tabular, relaciones entre entidades |
Esquema | Flexible, sin esquema fijo | Rígido, esquema predefinido |
Consultas | Basadas en claves | Basadas en conjuntos (SELECT) |
Transacciones | Soporte básico con comandos MULTI/EXEC | Completo soporte ACID |
Cuando decimos que Redis es una base de datos en memoria, estamos indicando que el servidor almacena todos los datos en la memoria principal (RAM), ya que es la manera más rápida para almacenar y recuperar datos. Esto permite que Redis funcione como memoria caché y también como unidad de memoria principal, con independencia de si los datos permanecen en la base de datos por mucho o poco tiempo. Así pues, en un servidor Redis con su uso principal, los datos no se guardan en el disco duro, sino en la memoria principal.
Gracias a ser un almacén clave-valor, ofrece un alto rendimiento y puede escalarse fácilmente. Para cada entrada se crea una clave mediante la que se puede volver a solicitar la información en cuestión. Esto implica que las entradas no necesitan estar relacionadas entre sí ni tampoco consultarse con varias tablas diferentes, sino que la información está disponible de manera directa.
¿Y si falla el servidor o se va la luz? ¿Corremos el riesgo de perder todos los datos? Para evitar que eso ocurra, Redis puede, o bien hacer regularmente un duplicado de todos los datos en un disco duro secundario (persistencia RDB - Redis Database), o bien guardar en un archivo de registro todas las órdenes necesarias para llevar a cabo una reconstrucción (persistencia AOF - Append Only File).
Finalmente, respecto a la escalabilidad, como solución NoSQL, si toda la información no cabe es un único nodo, el sistema puede escalar horizontalmente añadiendo más nodos. Si cada nodo puede almacenar 64GB RAM, y tenemos 4 servidores, podríamos almacenar hasta 256GB de datos en nuestro servidor Redis.
Hablemos de tamaños
Un millón de cadenas almacenadas en Redis ocupan aproximadamente 85MB de almacenamiento.
Una instancia vacía de Redis utiliza 3 MB de RAM.
Los valores en Redis son de 64 bits.
En teoría, Redis puede almacenar 2^32 claves en una única instancia Redis. En la práctica, hay servidores de una única instancia con 250 millones de claves.
Puesta en marcha¶
Para poner en marcha Redis, bien podemos instalarlo en nuestro sistema, usar un contenedor Docker o utilizar la solución Redis cloud. Para ello, consulta la sección de Redis en la página de Entorno.
Uso del cliente redis-cli¶
Aunque hayamos visto que existe un interfaz gráfico, de momento vamos a centrarnos en el uso mediante la consola y acceder al cliente interactivo mediante redis-cli
:
redis-cli
# 127.0.0.1:6379>
Si queremos conectarnos a una instancia remota, y con un usuario determinado (parámetro -u
), realizaremos una conexión similar a la siguiente, donde al conectarnos siempre se nos indicará a que host estamos conectados:
redis-cli -u redis://usuario:password@redis-16677.c339.eu-west-3-1.ec2.redns.redis-cloud.com:16677
redis-16677.c339.eu-west-3-1.ec2.redns.redis-cloud.com:16677>
Al ejecutar un comando, siempre recibiremos una respuesta en la línea inferior. Por ejemplo, vamos a comprobar la conectividad haciendo PING
:
127.0.0.1:6379> PING
# PONG
Si no hubiéramos podido conectarnos, habríamos recibido un mensaje de error. Mediante help
aparecerá, además de la versión instalada, una lista de opciones de ayuda, así como la posibilidad de obtener más información de un comando concreto:
127.0.0.1:6379> help
# redis-cli 7.2.5
# To get help about Redis commands type:
# "help @<group>" to get a list of commands in <group>
# "help <command>" for help on <command>
# "help <tab>" to get a list of possible help topics
# "quit" to exit
CRUD¶
En este apartado vamos a simular que queremos crear un acortador de URLs, del tipo bit.ly, de manera que cuando un usuario pone una URL corta, accederíamos a la URL larga, lo que también nos permite llevar un contador de las visitas a cada dirección.
Usaremos los comandos SET
y GET
para asignar y recuperar un valor de una clave. SET
siempre requiere dos parámetros, la clave y el valor, mientras que GET
sólo permite recuperar por la clave:
SET aitor-bd aitor-medrano.github.io/bd
# OK
GET aitor-bd
# "aitor-medrano.github.io/bd"
Letra inicial
La primera letra de los comandos normalmente puede indicar el tipo de datos sobre el que trabaja, el módulo de Redis que emplea o un tipo de operación específica. En este caso, todas las operaciones que empiezan por M
se consideran operaciones múltiples que operan sobre más de una clave o valor con el mismo comando.
Si queremos hacer más de una entrada de una sola vez usaremos MSET
y MGET
:
MSET aitor-iabd aitor-medrano.github.io/iabd aitor-blog aitor-medrano.github.io/iabd/blog
# OK
MGET aitor-bd aitor-iabd aitor-blog
# 1) "aitor-medrano.github.io/bd"
# 2) "aitor-medrano.github.io/iabd"
# 3) "aitor-medrano.github.io/iabd/blog"
Si queremos recuperar las claves existentes usaremos KEYS
, al cual le podemos pasar *
para mostrar todas o un prefijo para que muestre aquellas que lo cumplen (permite el uso de expresiones regulares):
KEYS aitor-*
# 1) "aitor-blog"
# 2) "aitor-bd"
# 3) "aitor-iabd"
SCAN & MATCH
Aunque KEYS
permita recuperar todas las claves, el problema es que bloquea el servidor mientras las recorre. Esto puede provocar problemas serios en entornos de producción, ya que mientras Redis ejecuta el comando KEYS
, el servidor queda bloqueado para atender otras operaciones. En bases de datos con millones de claves, esto puede significar interrupciones de servicio inaceptables.
Para evitar esto, se recomienda utilizan SCAN cursor [MATCH patrón] [COUNT cantidad] [TYPE tipo]
, el cual ofrece una alternativa eficiente, ya que funciona de manera incremental, devolviendo las claves en lotes. Veamos un ejemplo (a lo largo de la sesión iremos creando nuevas claves que ahora aparecen en el ejemplo):
SCAN 0
# 1) "7" # El cursor para la siguiente iteración
# 2) 1) "visitas"
# 2) "pedro:visitados"
# 3) "sitiosweb"
# 4) "aitor-bd"
# 5) "noticias"
# 6) "contador"
# 7) "aitor-dwes"
# 8) "usuario:aitor:nombre"
# 9) "tech"
# 10) "usuario:aitor:pwd"
# 11) "usuario:aitor"
SCAN 7
# 1) "0" # El cursor 0 indica que se ha completado la iteración
# 2) (empty array)
También podemos filtrar por las claves, así como restringir el tipo de valor:
SCAN 0 MATCH usuario:aitor* COUNT 15
# 1) "0"
# 2) 1) "usuario:aitor:nombre"
# 2) "usuario:aitor:pwd"
# 3) "usuario:aitor"
SCAN 0 TYPE "string" COUNT 10
# 1) "7"
# 2) 1) "aitor-bd"
# 2) "contador"
# 3) "aitor-dwes"
# 4) "usuario:aitor:nombre"
# 5) "usuario:aitor:pwd"
SCAN 0 TYPE "set"
# 1) "7"
# 2) 1) "sitiosweb"
# 2) "noticias"
# 3) "tech"
Las características principales de SCAN
son:
- Iteración incremental: Devuelve un cursor que se utiliza para continuar la iteración
- No bloqueante: Permite que otras operaciones se ejecuten mientras se realiza el escaneo
- Cobertura completa: Garantiza que se examinan todas las claves existentes
- Opciones de filtrado: Permite filtrar mediante patrones con
MATCH
- Control de rendimiento: El parámetro CO`UNT sugiere cuántas claves examinar por iteración
Para borrar una determinada clave usaremos DEL
y EXISTS
para comprobar si existe:
EXISTS aitor-iabd
# (integer) 1
DEL aitor-iabd
# (integer) 1
EXISTS aitor-iabd
# (integer) o
GET aitor-bd
# (nil)
Cadenas¶
Si nuestros valores son cadenas, podemos emplear una serie de operaciones para trabajar con ellos, como STRLEN
para recuperar el tamaño de un valor, GETRANGE clave inicio fin
para obtener una subcadena o APPEND
para añadir contenido al final
GET aitor-bd
# "aitor-medrano.github.io/bd"
STRLEN aitor-bd
# (integer) 26
GETRANGE aitor-bd 0 22
# "aitor-medrano.github.io"
GETRANGE aitor-bd 24 -1
# "bd"
APPEND aitor-bd "/"
# (integer) 27
GET aitor-bd
# "aitor-medrano.github.io/bd/"
Enteros¶
Aunque Redis almacene cadenas, también permite almacenar números enteros y realizar ciertas operaciones sobre ellos, como INCR para incrementar de uno en uno INCRBY para indicar la cantidad, y sus contrarios DECR y DECRBY:
SET contador 2
# OK
INCR contador
# (integer) 3
GET contador
# "3"
INCRBY contador 2
# (integer) 5
DECR contador
# (integer) 4
Casos de uso muy comunes de almacenamiento de número enteros pueden ser contar el número de clics que se realiza sobre un enlace, o controlar la cantidad de entradas disponibles de un evento/concierto/partido/festival, etc...
Espacios de nombres¶
Redis utiliza un concepto diferente al de las bases de datos tradicionales. En lugar de tener múltiples bases de datos separadas, proporciona bases de datos lógicas numeradas dentro de una única instancia. Por defecto, Redis cuenta con 16 bases de datos numeradas de 0 a 15, aunque este número se puede configurar en el archivo redis.conf
mediante la directiva databases
.
Podemos recuperar las bases de datos que tenemos mediante CONFIG GET DATABASES
:
127.0.0.1:6379> CONFIG GET DATABASES
1) "databases"
2) "16"
Para elegir qué base de datos queremos emplear, usaremos el comando SELECT
, que permite cambiar la base de datos actual a otro espacio de nombres (al cambiar de base de datos, si no empleamos la base de datos 0
, en el CLI aparecerá entre corchetes su número identificador):
127.0.0.1:6379> GET aitor-bd
# "aitor-medrano.github.io/bd"
127.0.0.1:6379> SELECT 1
# OK
127.0.0.1:6379[1]> GET aitor-bd
# (nil)
De esta manera, podemos crear espacios de nombres separados para diferentes aplicaciones o componentes de la misma aplicación.
Redis cloud
Si estás utilizando Redis en modo clúster en el cloud, este solo soporta la base de datos 0. Los comandos SELECT
con índices distintos de 0 no funcionarán en Redis Cluster.
Aunque podemos emplear SELECT
para cambiar de base de datos, algunos desarrolladores prefieren utilizar prefijos en las claves del tipo usuario:1:nombre
o producto:1:nombre
para diferencias espacios de nombres.
A pesar de sus limitaciones, el comando SELECT
puede ser útil en varios escenarios:
- Entornos de desarrollo/pruebas: Usar diferentes bases de datos para separar datos de prueba de datos de producción en la misma instancia.
- Migración de datos: Mover datos temporalmente a otra base de datos durante procesos de migración.
- Caché multi-nivel: Usar diferentes bases de datos para diferentes niveles de caché con políticas de expiración distintas.
- Aplicaciones simples: Para aplicaciones pequeñas donde no se justifica tener múltiples instancias de Redis.
Expiración¶
Una de las características más útiles es la capacidad de establecer un tiempo de vida (TTL, Time-To-Live) para las claves, lo que permite gestionar la caducidad automática de los datos, sin necesidad de implementar mecanismos de limpieza manuales.
Redis utiliza dos estrategias para eliminar claves expiradas:
- Eliminación pasiva: Cuando se accede a una clave, Redis comprueba si ha expirado y, en caso afirmativo, la elimina.
- Eliminación activa: Redis tiene un proceso que periódicamente muestrea claves aleatorias con tiempo de expiración y elimina las que han caducado.
Esto permite que Redis mantenga un buen rendimiento incluso con millones de claves con expiración.
Para ello, usaremos el comando EXPIRE clave segundos
, el cual permite asignar un tiempo de vida (en segundos) a una clave existente. Una vez transcurrido el tiempo especificado, la clave se elimina automáticamente.
EXPIRE aitor-blog 3600 # establecemos una clave con una hora de expiración
# (integer) 1
Otras posibilidad son utilizar EXPIREAT clave timestamp
que permite establecer un tiempo de expiración basado en una fecha y hora específica, expresada en timestamp UNIX (segundos desde 1 de enero de 1970), o PEXPIRE
que permite definir la expiración en milisegundos:
EXPIREAT aitor-blog 1742751722
PEXPIRE aitor-blog 30000
Si queremos saber cuanto tiempo le queda a una clave, usaremos el comando TTL clave
:
TTL aitor-blog # Comprobamos el tiempo restante
# (integer) 3283
Si la clave no tiene expiración asignada, devolverá -1
. En el caso de que la clave no exista, devolverá -2
, bien sea porque ya ha expirado o que nunca se creó.
Otra posibilidad de asignar la expiración es hacerlo al mismo tiempo que se asigna un valor. Así pues, en las operaciones tipo SET
podemos indicar el parámetro EX
con la cantidad de segundos (o PX
para la cantidad de milisegundos):
SET aitor-blog aitor-medrano.github.io/iabd/blog EX 3600
# (integer) 3283
Finalmente, si queremos cambiar el estado para que una clave ya no caduque y deje de ser volátil, debemos persistirla mediante PERSIST
:
PERSIST aitor-blog
# (integer) 1
La expiración de las claves se emplea para:
- Gestión de sesiones: expirar claves de sesión de usuarios tras un tiempo de inactividad.
- Caché temporal: almacenar datos temporalmente para evitar accesos frecuentes a bases de datos tradicionales.
- Colas de mensajes: eliminar mensajes antiguos automáticamente.
- Control de rate-limiting: implementar restricciones de uso por usuario con expiración automática.
Transacciones¶
De la misma forma que hemos visto en MariaDB, necesitamos de alguna manera poder agrupar dos o más operaciones como si fuera una operación atómica. Para ello, usaremos el comando MULTI
para inicial el bloque de instrucciones, y EXEC
para confirmar la transacción. En el caso de querer hacer un rollback, usaremos el comando DISCARD
:
127.0.0.1:6379> MULTI
OK
127.0.0.1:6379(TX)> SET aitor-dwes aitor-medrano.github.io/dwes2122
QUEUED
127.0.0.1:6379(TX)> INCR contador
QUEUED
127.0.0.1:6379(TX)> EXEC
1) OK
2) (integer) 5
Cabe destacar que al comenzar una transacción, en el CLI se mostrará el sufijo (TX)
tras el prompt para indicar que las operaciones forman parte de una misma transacción.
Estructuras de datos¶
La estructura de datos básica de Redis está formada por las llamadas Strings, es decir, cadenas simples de caracteres.
El uso de Strings permite almacenar datos de forma genérica, como por ejemplo, serializando cualquier dato en una cadena o utilizando documentos JSON. Conviene destacar que el tamaño máximo es de 512 MB.
Como convención de código, se utilizan los dos puntos (:
) como separador de las palabras o niveles en las claves:
MSET usuario:aitor:nombre "Aitor Medrano" usuario:aitor:pwd "123456"
# OK
MGET usuario:aitor:nombre usuario:aitor:pwd
# 1) "Aitor Medrano"
# 2) "123456"
Algunos patrones comunes para nombrar las claves son:
# Para datos de usuario
usuario:{id}:{campo}
# Para sesiones
sesion:{token}:{campo}
# Para datos por entorno
{entorno}:{tipo}:{id}
# Para caché
cache:{servicio}:{recurso}:{id}
El sistema, sin embargo, es también compatible con otras estructuras de datos. Veamos las más destacadas
Hash¶
-
Estructura
Un mapa o hash en Redis es similar a un documento JSON, donde se mapea una clave con un valor. Destacar que sus valores siempre serán cadenas, es decir, no puede anidar otros mapas o conjuntos.
Hashes en Redis Se utiliza para almacenar objetos ligeros, como las sesiones de usuario, los propios datos del usuario, visitantes, etc...
Todas sus operaciones comienzan por la letra
H
:HGET
,HSET
,HMGET
,HKEYS
,HVALS
,HINCRBY
,HDEL
, etc...
-
Comandos
Para interactuar con un Hash utilizaremos los comandos
HSET
para asignar valores,HKEYS
para recuperar todas las claves yHVALS
para recuperar todos los valores, oHGET
para recuperar una clave concreta:HSET usuario:aitor nombre "Aitor Medrano" pwd "123456" # OK HVALS usuario:aitor # 1) "Aitor Medrano" # 2) "123456" HKEYS usuario:aitor # 1) "nombre" # 2) "pwd" HGET usuario:aitor nombre # "Aitor Medrano"
Otros comandos más específicos son
HDEL
para elimina campos,HINCRBY
para incrementar un campo cierta cantidad,HLEN
para obtener la cantidad de campos,HGETALL
para recuperar todas las claves y valores yHSETNX
para asignar una valor sólo si la clave no existe (ya que si existe, medianteHSET
siempre la sustituye).
Lista¶
-
Estructura
Las listas en Redis son como un array de cadenas, teniendo en cuenta que los elementos se ordenan por orden de inserción. Pueden funcionar como colas FIFO (first in, first out) o como pilas LIFO (last in, first out).
Se implementan mediante listas enlazadas, lo que provoca que las operaciones en la cabeza y en la cola ocurran con complejidad constante, independientemente del tamaño de la lista. En cambio, acceder a un elemento determinado, supone recorrer la lista elemento por elemento. En este caso, es mejor utilizar conjuntos ordenados.
En Redis, la cabeza (head) es el extremo izquierda y la cola (tail) el derecho.
Listas en Redis Casos de uso:
- Implementar colas como estructuras de datos
- Cronogramas de mensajes (feed de una red social, logs recientes, etc...)
- Listado de tareas, para su procesamiento en el orden de adicción.
-
Comandos
Para interactuar con un lista utilizaremos los comandos
LPUSH
para insertar valores por la izquierda yLPOP
para sacarlos, y sus homónimosRPUSH
yRPOP
para hacerlo por la derecha. Si queremos recuperar un subconjunto de elementos, usaremosLRANGE
, mientras que para averiguar la longitud de la lista usaremosLLEN
.Supongamos que queremos asignarles a nuestros usuarios una lista de URL favoritas. Para ello, podríamos hacer:
RPUSH aitor:enlaces aitor-bd aitor-iabd aitor-blog # (integer) 3 LLEN aitor:enlaces # (integer) 3 LRANGE aitor:enlaces 0 -1 # 1) "aitor-bd" # 2) "aitor-iabd" # 3) "aitor-blog"
Todas las operaciones de listas utilizan un acceso 0-index, donde un valor negativo indica el número de pasos desde el final.
Para sacar elementos, podemos emplear
LREM
para a partir de una clave, cuantos elementos queremos quitar de un determinado valor (si ponemos 0, borrará todos los que coincidan, y si ponemos un número negativo, borrará los indicados pero empezando a buscar desde el final):LREM aitor:enlaces 0 aitor-blog # (integer) 1 LLEN aitor:enlaces # (integer) 2
Si queremos reducir una lista y quedarnos con una cantidad concreta de elementos, podemos emplear
LTRIM clave inicio fin
para, por ejemplo, asegurarnos que nuestra lista no contiene más de 10 elementos:LTRIM aitor:enlaces 0 9 # OK
Para eliminar y recuperar cada valor en el orden en el que se añadieron (de forma similar a una cola FIFO), al insertarlos por la derecha, debemos sacarlos por la izquierda (la cabeza) de la lista:
LPOP aitor:enlaces # "aitor-bd"
Si en cambio queremos que funcione como una pila, tras insertarlos con
RPUSH
, utililizaremosRPOP
para sacarlos. Estas operaciones tienen un coste computacional constante (lo que significa que el tamaño de la lista no impacta en el rendimiento).Si queremos sacar, con un único comando, valores de la cola para insertarla en la cabeza de otra, antiguamente podíamos hacerlo mediante el comando
RPOPLPUSH
(right pop, left push):RPOPLPUSH aitor:enlaces pedro:visitados "aitor-iabd"
El problema era doble. Por un lado, el comando se ha marcado como obsoleto, y por el otro, solo permitía sacar por la derecha e insertar por la izquierda. Por suerte, desde la versión 6.2, podemos emplear el comando
LMOVE origen destino <LEFT | RIGHT> <LEFT | RIGHT>
, el cual es más flexible al permitir sacar el elemento tanto de la izquierda como de la derecha y a su vez, volver a insertarlo a la izquierda o la derecha del destino. Así pues, podemos conseguir el mismo resultado mediante:LMOVE aitor:enlaces pedro:visitados RIGHT LEFT
Conjunto¶
-
Estructura
Los conjuntos se parecen a las listas en que almacenan una colección de cadenas, pero los elementos no están ordenados ni repetidos.
Sets en Redis Además de añadir y eliminar elementos de un conjunto, podemos realizar varias operaciones de conjuntos, como la unión, la intersección, la diferencia etc.... Estas operaciones se realizan dentro de Redis y son muy rápidas. Lo que no podemos realizar es un acceso secuencial.
¿Cuándo debemos considerar el uso de conjuntos? Siempre que no nos importe la cardinalidad o cuántos elementos tenemos de una misma clave. Es más, en ocasiones necesitamos realizar un almacenamiento de elementos únicos, sin requerir la sobrecarga de tener que realizar una búsqueda para saber si el elemento existía previamente.
Por ejemplo, podemos emplear conjuntos para almacenar la lista de usuarios únicos de una web, elegir el ganador de un sorteo así como encontrar usuarios o elementos que pertenecen a dos grupos distintos.
-
Comandos
Para añadir elementos a un conjunto utilizaremos SADD, de manera que podemos añadir diversos valores a una clave,
SMEMBERS
para recuperar todos los valores,SISMEMBER
para averiguar si un valor forma parte de un determinado conjunto:SADD noticias elpais.com eldiario.es xataka.com # (integer) 3 # Devuelve la cantidad de elementos añadidos SMEMBERS noticias # Devuelve todos los miembros # 1) "elpais.com" # 2) "eldiario.es" # 3) "xataka.com SISMEMBER noticias "xataka.com" # Comprueba si "xataka.com" está en el conjunto # (integer) 1 SISMEMBER noticias "eurogamer.es" # (integer) 0
Si queremos recuperar una cantidad de elementos aleatorios de un conjunto usaremos
SRANDMEMBER clave cantidad
, donde sicantidad
es positiva devolverá elementos sin repetir, pero si es negativa, permitirá elementos repetidos:SRANDMEMBER noticias 2 # 1) "elpais.com" # 2) "xataka.com" SRANDMEMBER noticias -2 # 1) "xataka.com" # 2) "xataka.com"
También podemos emplear las operaciones matemáticas de conjuntos, mediante
SINTER
para la intersección,SDIFF
la diferencia ySUNION
para la union:SADD tech xataka.com eurogamer.es # (integer) 3 SINTER noticias tech # Enlaces que aparecen en los dos conjuntos # 1) "xataka.com SDIFF noticias tech # Noticias que no son de tecnología # 1) "elpais.com" # 2) "eldiario.es" SUNION noticias tech # Todas las noticias, sin enlaces repetidos # 1) "elpais.com" # 2) "eldiario.es" # 3) "xataka.com" # 4) "eurogamer.es" # (integer) 0
Todas las operaciones sobre conjuntos ofrecen la posibilidad de almacenar el resultado en uno nuevo, así pues, podemos emplear
SINTERSTORE
,SDIFFSTORE
ySUNIONSTORE
respectivamente:SUNIONSTORE sitiosweb noticias tech # (integer) 4 SMEMBERS sitiosweb # 1) "elpais.com" # 2) "eldiario.es" # 3) "xataka.com" # 4) "eurogamer.es"
Igual que usamops
LMOVE
para mover elementos entre listas, podemos emplearSMOVE
para mover valores entre conjuntos. Otras operaciones que muy útiles sonSCARD clave
para averiguar su tamaño (cardinalidad),SPOP
para sacar un elemento cualquiera (al no estar ordenados) oSREM clave valor
si queremos eliminar un valor concreto.SCARD sitiosweb # (integer) 4 SREM sitiosweb eldiario.es # (integer) 1 SCARD sitiosweb # (integer) 3
Conjunto ordenado¶
-
Estructura
Un conjunto ordenado también es una colección de cadenas únicas. A diferencia de un conjunto normal, los valores de un conjunto ordenado están ordenados (elemental, querido Watson)
Sets ordenados en Redis ¿Cómo se realiza la ordenación? La ordenación se basa en las puntuaciones y el orden léxico (orden alfabético) de las cadenas. Así, cada cadena es única, aunque las puntuaciones pueden coincidir. ¿Cómo se realiza la puntuación de estos valores? Redis proporciona operaciones para que los usuarios puedan manipular una puntuación para un elemento del conjunto.
Los conjuntos ordenados son preferibles a las listas cuando el acceso rápido a un miembro concreto es más importante que la rapidez de inserción/eliminación, es decir, son más importantes las lecturas que las escrituras. Es por ello, que la complejidad temporal de la inserción/eliminación en un conjunto ordenado es O(N), donde N es el número de elementos del conjunto, ya que mantiene los valores ordenados, en vez la complejidad O(1) que tienen las listas. Así pues, podemos considerar un conjunto ordenado como una cola prioritaria de acceso aleatorio.
Los conjuntos ordenados de Redis son ideales para casos de uso como rankings de productos más comprados, visitados, etc... así como sistemas con puntuación, tipo las preguntas de Stack Overflow o posts en Reddit.
-
Comandos
Para añadir elementos a un conjunto ordenado usaremos la operacion
ZADD clave puntuación valor
,ZREM
para eliminarlos, mientras que medianteZRANGE clave inicio fin
podemos recuperar las claves entre un rango inclusivo (si queremos que no entren inicio o fin en el rango, les pondremos un paréntesis delante) por posición o puntuación (BYSCORE
), pudiendo recuperarlo en orden inverso (REV
) y/o con su puntuaciónWITHSCORES
:ZADD visitas 1000 aitor-bd 5000 aitor-iabd 66 aitor-blog # (integer) 3 ZRANGE visitas 0 -1 WITHSCORES # Todos los elementos con puntuaciones # 1) "aitor-blog" # 2) "66" # 3) "aitor-bd" # 4) "1000" # 5) "aitor-iabd" # 6) "5000" ZRANGE visitas 50 1500 BYSCORE # Filtrado por puntuaciones # 1) "aitor-blog" # 2) "aitor-bd" ZRANGE visitas (66 1500 BYSCORE # No incluye el 66 # 1) "aitor-bd" ZRANGE visitas (5000 66 REV BYSCORE WITHSCORES # No incluye el 5000, en orden descendente # 1) "aitor-bd" # 2) "1000" # 3) "aitor-blog" # 4) "66"
Han caído en desuso las operaciones
ZREVRANGE
,ZRANGEBYSCORE
,ZREVRANGEBYSCORE
, etc... ya que conZRANGE
y los parámetros adecuados podemos obtener los mismos resultados.Si lo que queremos es averiguar cuantos valores tienen una puntuación entre entre un rango determinado, usaremos
ZCOUNT clave inicio fin
:ZCOUNT visitas 50 1500 # (integer) 2
Para incrementar la puntuación de un elemento, podemos volver a añadirlo con la nueva puntuación, lo cual modifica la puntuación pero no añade un nuevo valor, o incrementarlo por un determinado valor mediante
ZINCRBY
, el cual devolverá un nuevo valor (o reducirlo mediante un valor negativo):ZINCRBY visitas 1 aitor-bd # "1001"
JSON¶
-
Estructura
Redis permite el uso de JSON como un tipo de datos, permitiendo almacenar, modificar y recuperar valores JSON, lo que en parte la convierte en una base de datos documental.
Un documento JSON está formado por pares de clave-valor, donde las claves son cadenas, pero los valores pueden ser de diferentes tipos, los cuales pueden ser: * numéricos: enteros y decimales * cadenas de texto * valores booleanos:
true
ofalse
, null (valor nulo), objetos (conjuntos de pares clave-valor anidados) y arrays (listas ordenadas de valores, que pueden incluir cualquier combinación de los tipos anteriores).Toda la interacción de Redis con estructuras JSON se realizan con el prefijo
JSON.
.
-
Comandos
Los comandos que más vamos a emplear son
JSON.SET
para asignar una cadena JSON a una clave yJSON.GET
para recuperar un valor, pudiendo realizar selección y filtrado de elementos.Como hemos comentado, para asignar un elemento usaremos el comando
JSON.SET clave ruta valor
, donderuta
será$
para indicar el raíz o una expresión JSONPATH si queremos añadir contenido en un lugar específico, y mediantevalor
le asignamos una cadena en formato JSON. Además, podemos pasar el parámetroNX
para indicar que lo cree si no existe oXX
para sobreescribir en caso de que ya exista. Veamos algunos ejemplos:JSON.SET usuario:1 $ '{"nombre": "Aitor Medrano", "altura": 182, "hobbies": ["baloncesto", "videojuegos"]}' # OK JSON.SET usuario:2 $ '{"nombre": "José Manuel Pérez"}' NX # NX: Lo crea si no existe # OK JSON.SET usuario:2 $ '{"nombre": "Andreu Medrano"}' XX # XX: Lo sobreescribe, sólo si ya existe. Si no, ni lo inserta
Si queremos modificar un documento, además de
JSON.SET
para campos sencillos, podemos utilizarJSON.ARRAPPEND
yJSON.ARRINSERT
al trabajar con arrays para añadir, respectivamente, elementos al final o en una posición determinada:JSON.SET usuario:1 '$.altura' 183 # Modificamos un campo # OK JSON.SET usuario:1 '$.ciudad' '"Elche"' # Agregamos un nuevo campo # OK JSON.ARRAPPEND usuario:1 '$.hobbies' '"big data"' # 1) (integer) 3 JSON.ARRINSERT usuario:1 '$.hobbies' 1 '"música"' # 1) (integer) 4
Para recuperar documentos usaremos
JSON.GET clave [ruta]
, donderuta
es una expresión JSONPath:JSON.GET usuario:1 # "{\"nombre\":\"Aitor Medrano\",\"altura\":183,\"hobbies\":[\"baloncesto\",\"m\xc3\xbasica\",\"videojuegos\",\"big data\"],\"ciudad\":\"Elche\"}" JSON.GET usuario:1 '$.nombre' # Un campo sencillo # "[\"Aitor Medrano\"]" JSON.GET usuario:1 '$.hobbies' # Un campo array # "[[\"baloncesto\",\"m\xc3\xbasica\",\"videojuegos\",\"big data\"]]" JSON.GET usuario:1 '$.hobbies[0]' # El primer elemento del array # "[\"baloncesto\"]" JSON.GET usuario:1 '$.nombre' '$.ciudad' # Varias rutas # "{\"$.nombre\":[\"Aitor Medrano\"],\"$.ciudad\":[\"Elche\"]}"
También podemos emplear
JSON.MGET
para recuperar la misma ruta de varias claves:JSON.MGET usuario:1 usuario:2 '$.nombre' # 1) "[\"Aitor Medrano\"]" # 2) "[\"Andreu Medrano\"]"
Finalmente, para eliminar elementos disponemos de
JSON.DEL
y para vaciarlosJSON.CLEAR
(vacía los arrays y los objetos y pone a cero los valores enteros). En el caso de arrays, podemos emplearJSON.ARRPOP
para sacar un elemento de una posición oJSON.ARRTRIM
para recortar el array a una subconjunto de los elementos:JSON.DEL usuario:1 '$.ciudad' # (integer) 1 JSON.CLEAR usuario:1 '$.altura' # Ponemos la altura a 0 # (integer) 1 JSON.ARRPOP usuario:1 '$.hobbies' 0 # Sacamos el primer elemento # 1) "\"baloncesto\"" JSON.GET usuario:1 # "{\"nombre\":\"Aitor Medrano\",\"altura\":0,\"hobbies\":[\"m\xc3\xbasica\",\"videojuegos\",\"big data\"]}" JSON.ARRTRIM usuario:1 '$.hobbies' 1 2 # Nos quedamos con los elementos del 1 al 2 # 1) (integer) 2 JSON.GET usuario:1 # "{\"nombre\":\"Aitor Medrano\",\"altura\":0,\"hobbies\":[\"videojuegos\",\"big data\"]}"
Otras operaciones comunes son
JSON.ARRLEN
para averiguar el tamaño de un array oJSON.TYPE
para obtener el tipo de un determinado campo.
JSONPath¶
En el módulo de lenguaje de marcas ya habéis utilizado JSONPath para hacer consultas sobre documentos JSON. Aún así, vamos a repasar su sintaxis, la cual se basa en el uso de selectores:
Símbolo | Significado | Ejemplo | Explicación |
---|---|---|---|
$ |
Raíz del documento | $.nombre |
Selecciona el campo "nombre" en la raíz |
. |
Acceso a propiedades | $.usuario.nombre |
Accede a propiedades anidadas |
[] |
Indexación de arrays | $.hobbies[0] |
Selecciona el primer elemento del array |
* |
Comodín para todos los elementos | $.usuario.* |
Selecciona todas las propiedades de usuario |
.. |
Búsqueda recursiva | $..nombre |
Busca "nombre" en cualquier nivel |
Preparando datos
Vamos a crear un documento JSON complejo, con datos de dos usuarios con elmentos anidados y uso de arrays, para ilustrar diferentes consultas:
JSON.SET usuarios $ '{
"usuarios": [
{
"id": 1,
"nombre": "Aitor Medrano",
"edad": 21,
"contacto": {
"email": "a.medrano@edu.gva.es",
"telefonos": ["636 123456", "686 567890"]
},
"hobbies": ["programación", "música", "viajes"],
"direcciones": [
{"tipo": "casa", "ciudad": "Elche"},
{"tipo": "trabajo", "ciudad": "Elche"}
]
},
{
"id": 2,
"nombre": "Juani Moya",
"edad": 18,
"contacto": {
"email": "j.moya@edu.gva.es",
"telefonos": ["696 543210"]
},
"hobbies": ["lectura", "música", "deporte"],
"direcciones": [
{"tipo": "casa", "ciudad": "Murcia"},
{"tipo": "trabajo", "ciudad": "Elche"}
]
}
]
}'
Para poder ejecutar la instrucción, bien necesitamos que esté en una única línea:
redis-cli JSON.SET usuarios $ '{"usuarios":[{"id":1,"nombre":"Aitor Medrano","edad":21,"contacto":{"email":"a.medrano@edu.gva.es","telefonos":["636 123456","686 567890"]},"hobbies":["programación","música","viajes"],"direcciones":[{"tipo":"casa","ciudad":"Elche"},{"tipo":"trabajo","ciudad":"Elche"}]},{"id":2,"nombre":"Juani Moya","edad":18,"contacto":{"email":"j.moya@edu.gva.es","telefonos":["696 543210"]},"hobbies":["lectura","música","deporte"],"direcciones":[{"tipo":"casa","ciudad":"Murcia"},{"tipo":"trabajo","ciudad":"Elche"}]}]}'
O podemos almacenar los datos en un archivo JSON (por ejemplo, usuarios.json
) y ejecutarlo desde fuera del CLI mediante:
redis-cli JSON.SET usuarios $ "$(cat usuarios.json)"
Para nuestras primeras consultas, usaremos los selectores básicos:
JSON.GET usuarios '$.usuarios[0]' # Recuperamos el primer usuario
# s"[{\"id\":1,\"nombre\":\"Aitor Medrano\",\"edad\":21,\"contacto\":{\"email\":\"a.medrano@edu.gva.es\",\"telefonos\":[\"636 123456\",\"686 567890\"]},\"hobbies\":[\"programaci\xc3\xb3n\",\"m\xc3\xbasica\",\"viajes\"],\"direcciones\":[{\"tipo\":\"casa\",\"ciudad\":\"Elche\"},{\"tipo\":\"trabajo\",\"ciudad\":\"Elche\"}]}]"
JSON.GET usuarios '$.usuarios[*].nombre' # Obtenemos el nombre de todos los usuarios
# "[\"Aitor Medrano\",\"Juani Moya\"]"
JSON.GET usuarios '$.usuarios[*].contacto.telefonos[0]' # Primer teléfono de cada usuario
# "[\"636 123456\",\"696 543210\"]"
Datos sin escapar
Si queremos recuperar los datos sin escapar las llaves, corchetes, etc..., desde fuera del cliente, podemos invocarlo pasándole la consulta y el parámetro --raw
:
redis-cli --raw JSON.GET usuarios '$.usuarios[0]'
# [{"id":1,"nombre":"Aitor Medrano","edad":21,"contacto":{"email":"a.medrano@edu.gva.es","telefonos":["636 123456","686 567890"]},"hobbies":["programación","música","viajes"],"direcciones":[{"tipo":"casa","ciudad":"Elche"},{"tipo":"trabajo","ciudad":"Elche"}]}]
Por ejemplo, podemos filtrar los datos haciendo uso de expresiones de filtrado mediante ?()
para restringir los documentos.
Las rutas dentro de la condición de filtro utilizan la notación de punto con @
para indicar el elemento actual del array o el valor actual del objeto, o $
para indicar el elemento de nivel superior. Es importante destacar que Redis no soporta el operador ?()
para filtrar arrays directamente en la consulta.
Por ejemplo:
# Nombre de los usuarios mayores de 20 años
JSON.GET usuarios '$.usuarios[?(@.edad < 20)].nombre'
# "[\"Juani Moya\"]"
# Nombre del usuario cuyo email es a.medrano@edu.gva.es
JSON.GET usuarios '$.usuarios[?(@.contacto.email == "a.medrano@edu.gva.es")].nombre'
"[\"Aitor Medrano\"]"
También podemos emplear ..
para realizar búsquedas recursivas:
JSON.GET usuarios '$..nombre' # Encontrar todos los elementos llamados "nombre"
# "[\"Aitor Medrano\",\"Juani Moya\"]"
JSON.GET usuarios '$..ciudad' # Encontrar todas las ciudades
# "[\"Elche\",\"Elche\",\"Murcia\",\"Elche\"]"
Una vez visto estas operaciones, cabe destacar que:
- Redis tiene soporte limitado para JSONPath complejo, por lo que si necesitamos hacer consultas avanzadas, bien necesitaremos hacerlas mediante un lenguaje de programación para realizar el procesamiento adicional u optar por una solución documental como MongoDB.
- La eficiencia depende del tamaño y complejidad del documento
Otras estructuras de datos menos comunes son:
- Bitmaps: estructura compacta que permite operaciones a nivel de bit.
- HyperLogLog: estimación según valores unívocos
- Stream: lista de strings o pares complejos de key-value
Puesto que Redis es un sistema de código abierto, hay muchos desarrolladores trabajando para ampliar el sistema. Los llamados módulos o ampliaciones aumentan el rango de funciones de la base de datos, que por lo demás es bastante sencilla, y adaptan el software a ámbitos de uso específicos.
Publicación-Suscripción¶
Existen diferentes sistemas de mensajería que permiten desacoplar el emisor de datos del receptor, como pueden ser RabbitMQ, Celery o incluso Apache Kafka en sistemas de Big Data. Si no necesitamos una solución tan potente, Redis ofrece un mecanismo de publicación-suscripción que permite a los clientes enviar y recibir mensajes en tiempo real.
Los clientes pueden suscribirse a canales y recibir mensajes publicados en esos canales por otros clientes. Este mecanismo es útil para implementar sistemas de mensajería, notificaciones en tiempo real, actualizaciones en tiempo real, etc.
Para ello, se emplean los siguientes comandos:
SUBSCRIBE canal \[canal …\]
: Se suscribe a uno o más canales.UNSUBSCRIBE \[canal \[canal …\]\]
: Se desuscribe de uno o más canales.PUBLISH canal mensaje
: Publica un mensaje en un canal.
Así pues, mediante la publicación-suscripción en Redis podemos implementar:
- Un sistema de notificaciones en tiempo real. Por ejemplo, se puede utilizar Redis para enviar notificaciones a los usuarios en tiempo real cuando se producen eventos importantes en la aplicación.
- Un sistema de chat en tiempo real. Por ejemplo, se puede utilizar Redis para enviar mensajes de chat entre usuarios en tiempo real.
Persistencia¶
Por defecto, la gestión de la persistencia en Redis implica que los datos no se almacenan instantáneamente en disco, sino que se realiza de forma periódica o a petición del cliente.
Para ello, en redis.conf
se especifica el número de cambios ocurridos antes de almacenar una instantánea de los datos en disco, lo que se conoce como la persistencia RDB (Redis DataBase). Los valores predeterminados son:
save 900 1 # Guarda cada 15 minutos si se modificó al menos 1 clave
save 300 10 # Guarda cada 5 minutos si al menos cambiaron 10 claves
save 60 10000 # Guarda cada 60 segundos si al menos cambiaron 10000 claves
Esto puede provocar pérdida de datos en caso de fallo. Para evitarlo, Redis dispone del archivo appendonly.aof
que guarda un registro para cada operación de escritura, lo que se conoce como persistencia AOF (Append Only File). Si el servidor cae antes de escribir en disco, cuando vuelva a estar disponible incluirá lo que esté pendiente.
appendonly yes
appendfsync everysec # Sincroniza cada segundo (opciones: always, everysec, no)
La elección entre un mecanismo y otro va a depender de las necesidades de la aplicación, evaluando la criticidad de los datos y del rendimiento. RDB es más eficiente, al utilizar un archivo único compacto, ideal para copias de seguridad. En cambio, puede suponer una posible pérdida de datos entre instantáneas
En cambio, como AOF registra todas las operaciones de escritura, ofrece mayor durabilidad y menor pérdida de datos, pero empleando archivos más grandes y con un peor rendimiento.
En resumen¶
Redis destaca por su velocidad extrema, permitiendo realizar operaciones en cuestión de microsegundos. Su flexibilidad no se limita a un simple sistema clave-valor, sino que ofrece estructuras de datos avanzadas, lo que lo convierte en una herramienta versátil para distintas aplicaciones.
Además, permite la ejecución de operaciones atómicas, como el incremento de valores con INCR
, garantizando la coherencia de los datos. Otra de sus ventajas es la gestión nativa del tiempo de vida de las claves (TTL
), lo que facilita la expiración automática de datos.
Sin embargo, Redis también presenta ciertas limitaciones. Su principal restricción es que los datos deben almacenarse en memoria RAM, lo que impone un límite de capacidad. Además, no impone una estructura de datos estricta, ya que no cuenta con validación de esquemas o tipos. Sus opciones de consulta son limitadas, ya que solo permite búsquedas por clave o patrones simples. A diferencia de las bases de datos relacionales, no soporta integridad referencial, por lo que no se pueden definir claves foráneas ni realizar uniones (JOIN
). También, dependiendo de su configuración, la durabilidad de los datos no está garantizada, existiendo la posibilidad de pérdida de información. Sus transacciones, aunque permiten la ejecución de múltiples operaciones, no disponen de un mecanismo de reversión (rollback
) real.
Redis es la opción ideal cuando se requiere acceso a los datos con latencias mínimas, especialmente en aplicaciones donde los datos pueden modelarse con estructuras simples. Sus casos de uso más comunes son sistemas de caché, contadores, colas y almacenamiento de información en tiempo real con alta concurrencia. Además, su capacidad de gestionar automáticamente la expiración de datos lo convierte en una herramienta valiosa en escenarios donde la información tiene un ciclo de vida determinado.
Referencias¶
- Redis University, portal formativo de Redis.io con diversos cursos sobre *Redis.
- Redis Cheat Sheet
- Seminario de Redis por Manuel Torres, de la Universidad de Almería.
- Tutorial de Redis de Ionos.
- El libro Redis Deep Dive, de Suyog Dilip Kale y Chinmay Kulkarni.
Actividades¶
-
AC1207. (RABD.7 // CE7c, CE7d, CE7e // 3p) Una vez puesto en marcha Redis, y utilizando cadenas cuyas claves utilicen el prefijo
ac1207pelis:
, se pide:- Inserta 3 títulos de películas (por ejemplo, usando las claves
ac1207pelis:1
,ac1207pelis:2
, etc...). - Inserta 2 películas con una sola instrucción.
- Comprueba si existe la primera película que has insertado, así como una que no debería existir.
- Recupera mediante una sola instrucción las dos primeras películas.
- Recupera todas las claves.
- Recupera las dos primeras claves.
- Elimina la tercera película.
- Asigna un tiempo de vida de 30 minutos a la segunda película.
- Crea una nueva película con un tiempo de vida de dos horas.
- Comprueba el tiempo de vida de la segunda película.
- Inserta 3 títulos de películas (por ejemplo, usando las claves
-
AR1208. Utilizando las hashes en Redis con el prefijo
ar1208pelis:
, se pide:- Crea un hash para añadir a la película
ar1208pelis:1
la propiedadtitulo
. - Para la misma película, mediante una única operación, añade las propiedades
anyo
yplataforma
(plataforma de streaming donde hemos visto la película, o biencine
otv
dependiendo del caso). - Recupera el año de la película.
- Recupera toda la información de la película.
- En otra clave, añade una nueva película con todas sus propiedades.
- Recupera todas las claves de la última película.
- Recupera todos los valores de la última película.
- En nuevas claves, añade dos películas más.
- Recupera los valores de la última película.
- Recupera todas las hashes existentes.
- Elimina el año de la última película.
- Averigua cuantos campos tiene la última película.
- Elimina la última película.
- Vuelve a recuperar todas las hashes existentes para comprobar que ya no existe.
- Crea un hash para añadir a la película
-
AC1209. (RABD.7 // CE7c, CE7d, CE7e // 3p) Utilizando las listas en Redis, se pide:
- Crea una lista que permita almacenar las series que marca un usuario como
ac1209watchlist
. - Añade 3 títulos de series a la lista por la izquierda.
- Añade 2 series a la lista por la derecha.
- Recupera el tamaño de la lista.
- Recupera todos las series.
- Recupera la primera y la última.
- Saca el último elemento insertado por la derecha.
- Comprueba si la lista tiene un elemento menos.
- Crea una lista que permita almacenar las series que marca un usuario como
-
AP1210. (RABD.7 // CE7c, CE7d, CE7e // 3p) Utilizando las listas de Redis, se pide simular una cola. Para ello:
- Crea una cola llamada
emails:pendientes
. - Añade 3 mensajes de email al final de la cola. Cada mensaje es un hash formado por
para
,asunto
ytexto
. - Procesa el primer mensaje (extráelo).
- Verifica cuántos mensajes quedan.
- Añade un mensaje prioritario al inicio de la cola.
- Procesa los mensajes restantes.
- Comprueba que quedan 0 mensajes.
- Crea una cola llamada
-
AC1211. (RABD.7 // CE7c, CE7d, CE7e // 3p) Utilizando los conjuntos en Redis, se pide:
- Crea un conjunto que permita almacenar bases de datos NoSQL dentro de
ac1211nosql
. - Añade al conjunto los valores
Redis
,MongoDB
yNeo4j
. - Vuelve a añadir al conjunto el valor
Redis
. - Recupera los elementos del conjunto.
- Crea otro conjunto que permita almacenar bases de datos relacionales dentro de
ac1211sql
. - Añade al conjunto los valores
MariaDB
,PostgreSQL
yOracle
. - Comprueba si el conjunto
ac1211sql
contieneRedis
. - Crea el conjunto
ac1211bd
con la union de los dos conjuntos. - Recupera cuantos elementos tiene el nuevo conjunto.
- Recupera los elementos del nuevo conjunto.
- Elimina del nuevo conjunto el valor
Neo4j
. - Comprueba si hay algún elemento compartido entre los dos conjuntos iniciales.
- Recupera dos elementos aleatorios de cada conjunto (sin repetidos)
- Recupera dos elementos aleatorios de cada conjunto (con repetidos repetidos)
- Crea un conjunto que permita almacenar bases de datos NoSQL dentro de
-
AP1212. (RABD.7 // CE7c, CE7d, CE7e // 3p) Utilizando los conjuntos ordenados en Redis, se pide:
- Crea el conjunto ordenado
ap1212bd
que permita almacenar bases de datos con una puntuación donde calificaremos nuestro conocimiento. - Añade al conjunto los valores
Redis
con 50 puntos,Neo4j
con 5 puntos,MariaDB
con 90 puntos yMongoDB
con 20 puntos. - Recupera los elementos donde tengamos un conocimiento entre 30 y 95 puntos.
- Recupera los elementos donde tengamos un conocimiento entre 20 y 90 puntos, pero sin incluir esos valores.
- Recupera los elementos donde tengamos un conocimiento entre 5 y 100 puntos, con las puntuaciones asociadas.
- Recupera el número de elementos del conjunto ordenado.
- Recupera todos los elementos de menor a mayor conocimiento.
- Recupera todos los elementos de mayor a menor conocimiento.
- Elimina el elemento
Neo4j
.
- Crea el conjunto ordenado
- AR1215. (RABD.1, RABD.7 // CE7c, CE7d, CE7e // 3p) De forma similar a las cheatsheets técnicas, crea una tabla resumen con los comandos más importantes que hemos trabajado en esta sesión.
- AR1216. (RABD.1, RABD.7 // CE1g, CE1h, CE1j, CE7a, CE7b, CE7c, CE7d // 3p) Una vez finalizada la unidad, responde todas las preguntas del cuestionario inicial, con al menos un par de líneas para cada una de las cuestiones.