Básicos Redis: Publish & Subscribe

Redis

Unas notas sencillas sobre publicación-suscripción en Redis, es la implementación de Redis de este patrón usando canales y clientes.

En Redis existen lo que se llama patrones de suscripción, que es una forma de suscribirse a varios canales a la vez que cumplan un patrón, este patrón está basado en el nombre (estilo glob), se soportan los siguientes:

  • ? Para un solo carácter
  • * Para múltiples caracteres
  • […] Caracteres alternos (h[ae]llo funciona con hello y hallo)
  • ^ Prefijos (no empieza por …)
PUBLISH channel messagePublica el mensaje message a los N suscriptores del canal channel que se hayan suscrito a los M patrones de suscripción, devolverá el numero de clientes que han recibido el mensajeO(N+M)
SUBSCRIBE channel-1… [channel-N]Suscribe al cliente al numero de canales N especificadoO(N)
UNSUBSCRIBE channel-1 [… channel-N]Elimina la suscripción del canal indicado (en el que hay N clientes) o de todos sino se indica ningunoO(N)
PUBSUB CHANNELS *Devuelve el número N de canales activosO(N)
PUBSUB NUMSUB channel-1 [… channel-N]Devuelve el número de suscriptores excluyendo suscriptores en patrones para los N canales solicitadosO(N)
PUBSUB NUMPAT [channel-1 … channel-N]Devuelve el número de suscriptores con patrones y el número de patronesO(1)
PSUBSCRIBE pattern1 […pattern-n]Permite suscribirse basado en el patrón de suscripción indicado añadiéndolo a los N patrones a los que ya estuviera suscritoO(N)
PUNSUBSCRIBE
pattern1 […pattern-n]
Elimina del sistema el patrón indicado, de los N patrones que tuviera el cliente, dentro de los M patrones que tiene el sistemaO(N+M)
Publicación suscripción
Básicos Redis: Publish & Subscribe

Básicos Redis: Estructuras de datos

Redis

Aquí indico unas notas sobre estructuras básicas, si un comando acepta varias opciones los comento en la sección de ejemplos.

Claves

Parejas clave valor:

  • Son únicas.
  • Por defecto si no existe se crea.
  • Almacenadas en formato binario (se puede cualquier elemento binario como clave).
  • Valores de clave de 512 MB de tamaño máximo.
  • Sensible a mayúsculas / minúsculas.
SET key value [EX seconds] [PX milliseconds|EX seconds] [NX|XX]Crea la clave de nombre key con valor valueO(1)
MSET key1 value1 key2 value2 … keyN valueNInserta varias claves a la vez con sus valores correspondientesO(N)
GET keyObtiene la clave de nombre keyO(1)
KEYS [pattern]Recupera todas las clavesO(N)
SCAN slot [MATCH pattern] [COUNT count]Recupera las claves por gruposO(1)/O(N)
DEL key1 key2Borra las claves indicadas, es un comando bloqueanteO(1)/O(N)/(OM)
UNLINK keyBorra la clave indicada de forma asíncronaO(1)/O(N)
EXISTS keyIndica si la clave existe (0 indica que no existe)O(1)
TTL keyTiempo restante de la clave antes de expirar en segundosO(1)
PTTL keyTiempo restante de la clave antes de expirar en milisegundosO(1)
INCR keyAumenta en 1 el valor de key (tiene que ser un número)O(1)
INCRBY key [-]incrAumenta o decrementa (-) en incr el valor de key (tiene que ser un número)O(1)
DECRBY key decrDecrementa en decr el valor de key (tiene que ser un número)O(1)
PEXPIRE key secondsCambia el tiempo de expiración de key en segundosO(1)
EXPIREAT key timestampIndica el momento en que expirará en tiempo unix en segundosO(1)
PEXPIREAT key timestamp_in_millisecondsIndica el momento en que expirará en tiempo unix en milisegundosO(1)
TYPE keyDevuelve el tipo de dato de keyO(1)
OBJECT [ENCODING| REFCOUNT| IDLETIME| FREQ| HELP] keyDevuelve información internal de keyO(1)
Claves

Aunque KEYS y SCAN sirven para lo mismo (devolver todas las claves) tienen algunas diferencias.

KEYSSCAN
Bloque hasta que terminaUsa un cursor para iterar, útil para producción
No es para producciónDevuelve una referencia a un grupo
Útil para depuraciónDevolverá 0 o más claves por llamada
Keys vs Scan

Ejemplos

SET claves:ejemplo:clave1 valor_nuevo
– Crea una clave de nombre claves:ejemplo:clave1 con valor valor_nuevo al no tener Redis espaciones de nombres suele ser interesante separar los elementos con «:» del elemento más general al específico
SET claves:ejemplo:clave1 valor_nuevo NX
– Crea la clave solo si no existía previamente (NX=No exist)
SET claves:ejemplo:clave1 valor_nuevo XX
– Crea la clave solo si exístia previamente
SET claves:ejemplo:clave1 valor_nuevo EX 7200
– Crea la clave claves:ejemplo:clave1 que expirará en 7200 segundos
SET claves:ejemplo:clave1 PX 50000
– Crea una clave que expirará en 50000 ms
SET claves:ejemplo:clave1 EX 50
– Crea una clave que expirará en 50 s (igual que el anterior)

GET claves:ejemplo:clave1
– Devuelve el valor de esta clave, en este caso valor_nuevo

KEYS claves:ejemplo:cl*
– Devuelve todas las claves que empiecen por cl*

SCAN 0 MATCH claves:ejemplo:cl*
– Devuelve todas las claves que empiecen por cl* empezando desde el princpio 0 devolverá un nuevo valor que se usará para la siguiente llamada, por ejemplo la salido puede ser:
1) «14848»
Entonces la siguiente llamada sería:
SCAN 14848 MATCH claves:ejemplo:1*
SCAN 14848 MATCH claves:ejemplo:1* 1000
– Indicamos que queremos buscar en bloques más grandes (1000)

Rendimiento

O(1): HDEL cuando borra un solo elemento, UNLINK, SCAN en una llamada
O(N): HDEL cuando borra varios elementos, siendo N el número de elementos, UNLINK en su hilo siendo N el número de elementos, SCAN para la iteración completa siendo N el número de elementos en la colección
O(M): HDEL cuando la clave eliminada contiene una estructura como lista, conjunto, conjunto ordenado o Hash, siendo M el número de elementos dentro de la esctructura

Hashes

Conjuntos de campos clave/valor.

  • Así como existe un comando para borrar campos (HDEL) no existe uno para añadir, tanto la creación como la adición de campos se hace con HSET
  • HMGET recomendado para pocas claves, si van a recuperarse muchas es mejor HSCAN
  • No existe un comando para decrementar
HSET key field1:value1 fieldN:valueN…Creación de un hashsetO(N)
HSETNX key field valueEstablece el valor value al compo field en key solo si no existía previamente, 1 indica que se cambió el valor y 0 lo contrarioO(1)
HGETALL keyDevuelve todos los campos del conjunto keyO(N)
HDEL key field1… fieldNElimina el campo field del conjunto keyO(N)
HGET key fieldObtiene el valor del campo field del conjunto keyO(1)
HMGET key field…fieldNObtiene las claves de los valores indicadosO(N)
HINCRBY key field valueIncrementa el campo field con la cantidad value (tiene que ser numérico)O(1)
HINCRBYFLOAT key field valueIncrementa el campo field con la cantidad value (tiene que ser numérico)O(1)
HSCAN key slot [MATCH pattern] [COUNT count]Devuelve todos los campos de key O(1)/O(N)
HEXISTS key fieldComprueba si existe el campo field en key (1 existe 0 no)O(1)
HKEYS keyObtiene todas las claves (N) de un keyO(N)
HVALS keyObtiene todos los valores (N) de una keyO(N)
Hashes

Ejemplos

HSCAN hash:full 0 MATCH claves:ejemplo:cl*
– Tiene el mismo efecto que SCAN para claves pero sobre el hash hash:full

Rendimiento

O(1): HSCAN en una llamada
O(N): HGETALL (siendo n el número de campos), HSCAN para la iteración completa siendo N el número de elementos en la colección

Listas

Se pueden implentar como colas o como pilas añadiendo (PUSH) y quitando (POP) elementos de los extremos. Admite hasta 4 billones de elementos.

RPUSH list value1 …valueNInserta por la derecha el elemento value en la lista listO(N)
LPUSH list value1 …valueNInserta por la izquierda el elemento value en la lista listO(N)
LPOP list [N]Devuelve y elimina N elementos por la izquierda de la lista listO(N)
RPOP listDevuelve y elimina N elementos por la derecha de la lista listO(N)
LRANGE list start [-]stopDevuelve los N elementos de la lista list desde el índice start (S) hasta stop (índice basado en 0) empezando por la izquierda si stop es negativo empezará desde la derechaO(S+N)
LLEN listDevuelve el número de elementos de la lista listO(1)
LTRIM list start [-]stopElimina los N elementos de la lista list excepto los contenidos entre los índices start y stop (índice basado en 0) empezando por la izquierda y si stop es negativo contará desde la derechaO(N)
LINSERT key [after|before] key1 valueInserta en la lista key antes (before) o después (after) del emento key en la posición N el valor valueO(N)
LINDEX key indexDevuelve el elemento en el índice (index) especificado de la lista de tamaño N keyO(N)
LSET key index valueInserta el elemento value en el índice (index) especificado de la lista de tamaño N keyO(N)
LREM key count elementElimina las count (M) primeras ocurrencias del elemento element en la lista de tamaño N keyO(M+N)
Lists

Ejemplos

Teniendo una lista a,b,c,d,e,f llamada list
LTRIM list 0 4
Devuelve todos los elementos desde a hasta e
LTRIM list 1 -2
Devuelve los elementos b,c,d,e (f es el elemento -1 y e es el elemento -2)
LRANGE list 0 -1
Devuelve todos los elementos de la lista

Rendimiento

O(1): LPOP, RPUSH, LLEN
O(s+n): LRANGE (donde s es la distancia al primer elemento y n el número total de elementos)

Conjuntos

Colección no ordenada de elementos no duplicados

SADD key element1 …elementNAgrega los elementos elementX al conjunto de clave keyO(N)
SCARD keyDevuelve el número de elementos en el conjunto de clave keyO(1)
SISMEMBER key elementIndica si el elemento element está dentro del conjunto (devuelve 1) o no (devolverá 0)O(1)
SINTER key1 key2 key3 …Realiza la intersección y devuelve los elementos de los conjuntos de claves keyXO(N*M)
SDIFF key1 …keyXRealiza la diferencia de los conjuntos keyXO(N)
SREM key element …elementNQuita los N elementos element al conjunto de clave keyO(N)
EXPIREAT key timeEl conjunto de clave key expirará en el tiempo indicado en time (Unix timestamp)O(1)
SSCAN key slot [MATCH pattern] [COUNT count]Devuelve todos los campos de keyO(1)/O(N)
SPOP key [count]Devuelve count (N) elementos aleatorios de keyO(1)
SUNION key1 … keyXRealiza la unión de todos los elementosO(N)
Conjuntos

Ejemplos

Teniendo un conjunto A = {A, b, C} y B = {a, b, C}:
SDIFF A B
– Devolverá la diferencia de conjuntos, los elementos que están en A y no están en en B, es decir «A»
SSCAN set:full 0 MATCH claves:ejemplo:cl*
– Tiene el mismo efecto que SCAN para claves pero sobre el hash hash:full

Rendimiento

O(N*M): SINTER, siendo N la cardinalidad del conjunto pequeño y M el número de conjuntos
O(N): SDIFF y SUNION donde N es el número total de elementos de todos los conjuntos

Conjuntos ordenados

Una colección ordenada de elementos únicos, para ordenarlos a cada elemento se le asocia una puntuación (score) que será el valor usado para la ordenación.
Si esta puntuación es igual se realiza un orden lexicográfico basado en el nombre del key. Útil para:

  • Colas con prioridad
  • Mostrar paneles de puntuación con baja latencia
  • Índices secundarios
ZADD key [NX|XX] [CH] [INCR] score memberAgrega un elemento a key (tamaño N) con la puntuación score y el campo memberO(log(N))
ZINCRBY key [-]increment memberIncrementa o decrementa [-] el valor del campo member a key (tamaño N) en un valor increment.O(log(N))
ZRANGE key [BYSCORE|BYLEX] [REV] [LIMIT offset count] [WITHSCORES]Devuelve M elementos desde el score más bajo al más alto de key (tamaño N)O(log(N)+M)
ZRANK key memberDevuelve la posición de member dentro de key ordenada de menor a mayor (si devuelve 0 tendría el score más bajo)O(log(N))
ZREVRANK key memberDevuelve la posición de member dentro de key ordenada de mayor a menor (si devuelve 0 tendría el score más alto)O(log(N))
ZSCORE key memberDevuelve el score del elemento member dentro del conjunto de clave keyO(1)
ZCARD keyDevuelve el número de elementos en el conjunto de clave keyO(1)
ZREM key value1 …valueNElimina M elementos del key (tamaño N) por nombreO(M*log(N))
ZREMRANGEBYRANK key min maxElimina M elementos de key (tamaño N) entre los índices start y stop (índice basado en 0) empezando por la izquierda y si stop es negativo contará desde la derechaO(log(N)+M)
ZREMRANGEBYLEX key min maxElimina M elementos de key (tamaño N) en el rango lexicográfico entre start y stop (índice basado en 0) empezando por la izquierda y si stop es negativo contará desde la derecha O(log(N)+M)
ZREMRANGEBYSCORE key min maxElimina M elementos de key (tamaño N) cuya puntuación esté entre start y stop (índice basado en 0) empezando por la izquierda y si stop es negativo contará desde la derechaO(log(N)+M)
ZCOUNT key min maxDevuelve el número de elementos con una puntuación entre min y max en key (tamaño N) O(log(N))
ZINTERSTORE destination numkeys key1..keyN [WEIGHTS weight [weight …]] [AGGREGATE SUM|MIN|MAX]Realiza la intersección de numkeys conjuntos key1… y almacena el valor en destinationO(N*K)+O(M*log(M)) 
ZUNIONSTORE destination numkeys key1…keyN [WEIGHTS weight [weight …]] [AGGREGATE SUM|MIN|MAX]Realiza la union de numkeys conjuntos key1… y almacena el valor en destinationO(N)+O(M log(M))
Sorted Sets

Ejemplos

ZREMRANGEBYRANK list:cash 9 -1
– Elimina desde el elemento 9 hacia la derecha, es decir, el último (j)
ZRANGEBYSCORE list:cash (3 +inf
– Devuelve los elementos que tenga un score superior a 3 (3 hasta el final de la lista +inf
ZADD claves:ejemplo:clave1 30 value1 NX
– Crea la clave solo si no existía previamente (NX=No exist)
ZADDclaves:ejemplo:clave1 30 value1 XX
– Actualiza la clave solo si exístia previamente
ZADD claves:ejemplo:clave1 30 value1 CH
– Devuelve solo los elementos que hayan cambiado, por defecto devuelve los creados
ZADD claves:ejemplo:clave1 30 value1 INC
– Se comporta como ZINCRBY
ZRANGE claves:ejemplo 10 20 BYLEX
– Devuelve los elementos con score entre 10 y 20, los que tengan el mismo score estarán ordenados lexicograficamente
ZRANGE claves:ejemplo 10 20 REV
– Devuelve los elementos en orden inverso
ZRANGE claves:ejemplo 10 20 LIMIT 1 9
– Devuelve los elementos desde el 1 hasta el 19 (si count es negativo devuelve todos los elementos desde offset).

Rendimiento

O(N*K)+O(M*log(M)): ZINTERSTORE siendo N el conjunto más pequeño, K el número de conjuntos y M el número de elementos en el conjunto resultante

Bit data

Conjuntos de de bits, el offset se entiende como el desplazamiento dentro del mapa de bits de tamaño, por ejemplo un offset de 9 indicaría la novena columna de la primera fila quedando así 0000 0001 en un caso más general usaremos la fórmula offset = Y * MAX_WIDTH + X por lo que si quisiéramos marcar la primera fila de la novena columna en un mapa de tamaño N (=MAX_WIDTH) tendríamos: (suponemos un tamaño de N=20)
offset = 1 * 20 + 9 = 29 y el y el mapa de bits sería 0000 0000 0000 0000 0000 000 0000 1, si juntamos las dos coordenadas (9,0) y (9,1) y lo apilamos en líneas de 20 (N) queda:

00000000000100000000
00000000000100000000

Offset se puede indicar también usando # en este caso Redis calcula la posición del bit dependiendo del tamaño del tipo, por ejemplo #1 para u8 sería el elemento 8*1 de esta forma se tiene un número de elementos cada uno con un valor y tamaño fijo.

SETBIT key offset valueEstablece value (1 o 0) al elemento offset dentro del mapa de bits keyO(1)
GETBIT key [-]offsetRecupera el valor del bit para el mapa key y offset especificado, si es negativo se excluye la parte especificadaO(1)
BITCOUNT offset keyDevuelve el número de bits a 1 en el mapa key a partir de offsetO(N)
BITFIELD key
[get|set|incrby] type offset value [overflow wrap| sat|fail]
Devuelve (get) se establece (set) o incrementa (incrby) un valor value a un elemento type, definido como u para unsigned e i para signed seguido del tamaño en bits, por ejemplo u5, los comandos get and set se puede acumular en la misma instrucción bitfieldO(1)
BITOP [and|or|xor|not] key key1 key2Ejecuta la operación [or] sobre key1 y key2 y almacena el resultado en keyO(N)
BITPOS key [0|1|start end]Busca en key el valor 0 o 1 según se indique, si se especifican dos valores indica un intervalo a buscar, en este caso el valor 0.O(N)
Mapa de bits

Datos geoespaciales

Permite guardar datos usando coordenadas (latitud, longitud), se almacenan codificados en GeoHash (52 bits), se almacenan como un sorted set donde GeoHash es el score por lo que los mismos comandos de sorted set se pueden usar también aquí.

GEOADD key longitude1 latitude1 member … [longitudeN latitudeN]Añade una ubicación name al conjunto key de N elementos usando la longitud y latitud especificada, si se le llama con los mismos datos actualizará la posición existente.O(log(N))
GEOSEARCH key [FROMLONLAT longitude latitude] [BYRADIUS radius m|km|ft|mi] [BYBOX width height m|km|ft|mi][WITHDIST] [WITHCOORD] [ASC | DESC] [COUNT n]Devuelve los N sitios en el radio (byradius) o caja (bybox) indicado de los M existentes, usando como centro la longitud y latitud especificada o el ancho y alto, WITHDIST devuelve la distancia, WITHCOORD devuelve también las coordenadas, usando ASC se devolverán los resultados en orden empezando por la más cercana o viceversa usando DESC, se puede limitar el número de resultados a devolver con COUNT, unit es la unidad de medida a devolver: m (metros) km (kilometros) mi (millas) ft (pies).O(N+log(M))
GEOSEARCHSTORE store source [FROMLONLAT longitude latitude] [BYRADIUS radius m|km|ft|mi] [BYBOX width height m|km|ft|mi] [ASC | DESC] [COUNT n]Este comando es como GEOSEARCH pero almacena los resultados en el store indicado, si se usa la opción STOREDIST almacena los resultados en un conjunto ordenado con la distancia al centro desde el círculo o caja.O(N+log(M))
GEOHASH key member1 … [memberN]Devuelve el valor de GeoHash para el elemento indicado dentro del sorted set de N elementosO(log(N))
GEOPOS key member1 … [memberN]Devuelve la longitud y latitud de todos los N elementos solicitados dentro del conjunto keyO(N)
GEODIST key member1… [memberN] [unit]Devuelve la distancia entre dos elementos en la unidad indicada: m (metros) km (kilometros) mi (millas) ft (pies).O(log(N))
Geoposición
Básicos Redis: Estructuras de datos

Básicos Redis: Características

Redis

Instalación

Hay varias opciones de instalar Redis, tanto en la nube como en local, así como un par de opciones interesantes de clientes para acceder a hacer consultas.

Comandos de sistema

Una pequeña lista de comandos básicos de sistema:

DBSIZEDevuelve el número de keys en la base de datos seleccionada
OBJECT ENCODING KEYDevuelve el tipo de dato de key
Comandos básicos

Transacciones

Manejo de transacciones en Redis, Redis cumple ACID.

Detalles:

  • No se permiten transacciones anidadas.
  • DISCARD no ejecuta ningún comando, no existe el concepto de rollback porque la cola de comandos no se ejecuta hasta usar EXEC.
  • Redis implementa concurrencia optimista.
MULTIComienzo de una transacción
EXECEjecuta la cola de comandos
DISCARDDescarta los comandos
WATCH keyObserva una key, si esta cambia entonces no se ejecuta la transacción, este comando se ejecuta antes de MULTI, este comando es local no afecta a transaccciones de otros procesos
UNWATCH keyDeja de observar todas las keys, si la transacción es correcta se ejecuta un UNWATCH automático de todas las keys que se estuvieran observando
Transacciones

Básicos Redis: Características