Está en la página 1de 151

TECNOLOGÍA

ANTONIO SARASA
INTRODUCCIÓN
A LAS BASES DE DATOS

NoSQL
CLAVE-VALOR USANDO

REDIS
Introducción a las bases de
datos NoSQL clave-valor
usando Redis
Antonio Sarasa
Director de la colección Manuales (Tecnología): Toni Pérez

Diseño de la colección: Editorial UOC


Diseño de la cubierta: Natàlia Serrano

Primera edición en lengua castellana: abril 2019

© Antonio Sarasa, del texto

© Editorial UOC (Oberta UOC Publishing, SL) de esta edición, 2019


Rambla del Poblenou, 156
08018 Barcelona
http://www.editorialuoc.com

Realización editorial: Reverté-Aguilar

ISBN: 978-84-9180-485-7

Ninguna parte de esta publicación, incluyendo el diseño general y de la cubierta, puede ser copiada, reproducida,
almacenada o transmitida de ninguna forma ni por ningún medio, ya sea eléctrico, químico, mecánico, óptico, de
grabación, de fotocopia o por otros métodos, sin la autorización previa por escrito de los titulares del copyright.
Autor

Antonio Sarasa
Es licenciado en Ciencias Matemáticas, especialidad en Ciencias de la
Computación, por la Facultad de Matemáticas de la Universidad Complutense
de Madrid. Posteriormente estudió las ingenierías técnicas de Informática de
Gestión e Informática de Sistemas en la Universidad Nacional de Educación
a Distancia (UNED). También obtuvo el graduado en Ingeniería Informática
por la Universitat Oberta de Catalunya (UOC). Es doctor en Informática por la
Universidad Complutense de Madrid (UCM).
Actualmente es profesor contratado doctor en el Departamento de Sistemas
Informáticos y Computación de la Facultad de Informática de la UCM.
Asimismo, ha sido profesor tutor de asignaturas de las carreras de Informática
en varios centros asociados de la UNED, y es consultor de la asignatura Bases de
Datos NoSQL del máster de Business Intelligence de la UOC.
Sus áreas de investigación se centran en la aplicación de las técnicas de proce-
sadores de lenguajes y compiladores al desarrollo de aplicaciones. Asimismo,
ha trabajado en temas de patrimonio digital y e-learning, entre los que destaca su
participación en el proyecto estatal de la red de repositorios de material educativo
digital Agrega. Ha realizado más de cincuenta publicaciones en congresos, revis-
tas nacionales e internacionales.
Es miembro de varios comités de estandarización de AENOR.
stelibroestádeidcadoam
E ishiojs.
© Editorial UOC Índice

Índice

Prólogo ............................................................................................ 13
Antonio Sarasa

Capítulo I. Introducción a las bases de datos NoSQL


orientadas hacia agregados ................................................. 15
1. Introducción.......................................................................... 15
2. Las bases de datos NoSQL ................................................ 15
3. Características comunes de las bases de datos
NoSQL................................................................................... 23
4. Bases de datos NoSQL orientadas hacia agregados....... 28
5. Bases de datos NoSQL documentales.............................. 35
6. Bases de datos NoSQL de tipo clave-valor ..................... 36
7. Bases de datos NoSQL orientadas a columnas............... 38
Bibliografía.................................................................................. 40

Capítulo II. Introducción a Redis.


Una base de datos NoSQL de tipo clave-valor ............. 41
1. Introducción.......................................................................... 41
2. Principales características.................................................... 42
3. Instalación de Redis ............................................................. 45
4. Bases de datos en Redis ...................................................... 49
Bibliografía.................................................................................. 55

Capítulo III. Estructuras de datos en Redis ....................... 57


1. Introducción.......................................................................... 57
2. Cadenas.................................................................................. 57

9
© Editorial UOC Introducción a las bases de datos NoSQL

3. Listas....................................................................................... 63
4. Hash ........................................................................................ 67
5. Conjuntos .............................................................................. 70
6. Conjuntos ordenados .......................................................... 74
7. HyperLogLog........................................................................ 80
Bibliografía.................................................................................. 83

Capítulo IV. Persistencia, replicación


y particionamiento ................................................................. 85
1. Introducción.......................................................................... 85
2. Persistencia ............................................................................ 85
2.1. Redis Database (RDB)................................................. 85
2.2. Append-only file (AOF)................................................... 88
2.3. Replicación..................................................................... 90
2.4. Particionamiento........................................................... 94
Bibliografía.................................................................................. 99

Capítulo V. Otros aspectos del uso de Redis....................... 101


1. Introducción.......................................................................... 101
2. El sistema publicador/suscrito .......................................... 101
3. Transacciones........................................................................ 105
4. Sistema de canalización o pippeling..................................... 109
5. El lenguaje Lua de scripting.................................................. 110
6. Operaciones de gestión....................................................... 118
6.1. Gestión de conexiones ................................................ 118
6.2. Gestión de la seguridad ............................................... 118
6.3. Gestión del servidor..................................................... 119
6.4. Gestión de copias de seguridad.................................. 121
7. Acceso a Redis usando Python.......................................... 122
Bibliografía.................................................................................. 127

10
© Editorial UOC Índice

Capítulo VI. Ejemplo de uso de Redis.................................. 129


1. Introducción.......................................................................... 129
2. Elementos de información ................................................. 129
2.1. Usuario ........................................................................... 130
2.2. Mensajes propios .......................................................... 131
2.3. Mensajes de las personas a las que se sigue ............. 133
2.4. Personas a las que se sigue y personas seguidas...... 135
2.5. Almacenar mensajes de los seguidores ..................... 139
2.6. Eliminación de mensajes ............................................. 142
3. Conclusión............................................................................. 143
Bibliografía.................................................................................. 145

Conclusión...................................................................................... 147

11
© Editorial UOC Prólogo

Prólogo

El mundo de las bases de datos ha cambiado en los últimos


años con la llegada del fenómeno denominado big data. El para-
digma de persistencia más extendido hasta ese momento eran las
bases de datos relacionales. Cualquier sistema de información uti-
lizaba el modelo relacional para almacenarla. Este modelo ofrece
grandes ventajas tales como un sistema de transacciones que ase-
gura la consistencia de la información; el lenguaje SQL, que
constituye un lenguaje de consultas estándar; el modelo relacional,
que constituye un modelo formal en el que se sustentan estas
bases de datos; así como otras características como el rol de ele-
mento de integración entre diferentes aplicaciones. Sin embargo,
las necesidades de persistencia en el big data cambian sustancial-
mente. Así, hay varios elementos clave del cambio. En primer
lugar, la cantidad de datos que es necesario procesar; se trata de
enormes cantidades de datos cuya generación es casi inmediata
y cuyo tamaño aumenta de manera exponencial. Por otro lado,
existe la necesidad de procesarlos casi en tiempo real, dado que
el valor de la información decrece al pasar el tiempo. Y por últi-
mo, los formatos y estructuras de los datos. En este contexto, los
datos pueden ser de cualquier forma, pueden tener estructura o
no tenerla y, en caso de tenerla, esta puede cambiar de manera
dinámica. Todas estas nuevas características chocan con las de las
bases de datos relacionales, que esperan datos con una estructura
regular, en cantidades estables y con una capacidad de procesa-
miento determinada. Estos aspectos constituyen elementos clave
en este cambio, dado que la forma más eficiente de adaptarse a

13
© Editorial UOC Introducción a las bases de datos NoSQL

estas necesidades de procesamiento han sido soluciones de escala-


miento horizontal cuya ejecución se basa en clústers de máquinas.
Y precisamente este ambiente de ejecución no es el más adecuado
para una base de datos relacional diseñada para entornos centra-
lizados. Asimismo, la necesidad de disponer de un esquema de
estructuración de la información previo a su almacenamiento, lo
hace incompatible con este nuevo contexto de procesamiento de
información con estructuras cambiantes.
En este libro se distinguen dos partes. En el primer capítulo se
pretende realizar una introducción a los conceptos fundamenta-
les relacionados con las bases de datos NoSQL. A continuación,
los restantes capítulos se centran en una base de datos NoSQL
concreta: Redis. Se trata de una de las bases de datos de tipo
clave-valor más utilizadas y sirve para ilustrar todas las posibilida-
des que ofrecen este tipo de sistemas de persistencia. Para ello, el
libro se estructura en un conjunto de capítulos donde se describe
cómo realizar su instalación, su arquitectura, sus estructuras de
datos y se realiza una introducción a los tópicos sobre persisten-
cia, particionamiento y replicación de la información. Asimismo,
existe otro capítulo donde se tratan otros aspectos interesantes
de esta base de datos tales como el lenguaje de scripting Lua o
el sistema transaccional implementado en Redis. Por último, se
presenta un ejemplo de aplicación de la base de datos Redis para
la construcción de una red social similar a Twitter.
Espero que el libro le resulte ameno al lector y que cumpla su
objetivo de servir de medio de acercamiento a este nuevo ámbito
de las bases de datos NoSQL, en particular a Redis.
Madrid, 30 de enero de 2019

Antonio Sarasa

14
© Editorial UOC Capítulo I. Introducción a las bases…

Capítulo I
Introducción a las bases de datos NoSQL
orientadas hacia agregados

1. Introducción

Las bases de datos orientadas hacia agregados son un tipo de


bases de datos NoSQL que presentan unas características particu-
lares en cuanto a la organización de la información. Es por ello
que este capítulo se estructura de la siguiente forma. En primer
lugar se realiza una breve descripción acerca de qué son las bases
de datos NoSQL y se muestran sus principales características. A
continuación, se introducen las bases de datos orientadas hacia
agregados y se muestra el modelo de datos común que compar-
ten. Para finalizar, se describen las familias concretas de este tipo
de bases de datos que existen: las documentales, las orientadas
hacia columnas y las de tipo clave-valor.

2. Las bases de datos NoSQL

La aparición del fenómeno denominado big data tiene impli-


caciones en muchos aspectos tecnológicos, y en particular en el
contexto de los mecanismos de persistencia de la información.
Durante décadas, el modelo más utilizado para almacenar la
información fueron las bases de datos relacionales. Se trata de
un modelo que presenta unas características muy ventajosas en

15
© Editorial UOC Introducción a las bases de datos NoSQL

cuanto a las necesidades de persistencia que existían antes del big


data. Así, se pueden destacar las siguientes:

• Un modelo de concurrencia. Un problema habitual que se


presenta en la explotación de datos es la gestión de varias
aplicaciones que están manipulando los mismos almacenes de
datos. Esto requiere coordinar todas las aplicaciones que están
accediendo a ellos y modificándolos para evitar que se pro-
duzcan inconsistencias en la información. La gestión manual
de la concurrencia es muy compleja y puede dar lugar a erro-
res con facilidad. En este sentido, el modelo relacional ofrece
un mecanismo de transacciones que garantiza la consistencia
de la información frente a las operaciones de manipulación
realizadas por un conjunto de aplicaciones que se ejecutan
concurrentemente. Aunque el modelo puede dar lugar a
errores, también ofrece mecanismos que permiten revertir
las acciones realizadas por una transacción con el objetivo de
mantener un estado de consistencia en la información.
• Un mecanismo de integración. En muchas ocasiones un sis-
tema informático consiste en un conjunto de aplicaciones
independientes que deben coordinar sus acciones para llevar a
cabo la funcionalidad del sistema. Esta coordinación normal-
mente se traduce en acciones del tipo productor-consumidor,
es decir, una aplicación produce unos datos que otra aplica-
ción utiliza. Una forma de implementar esta interacción es
utilizando una única base de datos que contenga aquellos
que son manipulados de forma común y coordinada por
las diferentes aplicaciones, de esta manera la base de datos
sirve de mecanismo de integración del sistema informático.
Ahora bien, tal como se indicaba anteriormente, un requisito
para conseguir estas características es la disponibilidad de un

16
© Editorial UOC Capítulo I. Introducción a las bases…

sistema de concurrencia que garantice la consistencia de las


manipulaciones que realiza cada aplicación sobre los datos.
• Un modelo de persistencia de datos. Existen diferentes for-
mas de mantener la información disponible de forma perma-
nente como, por ejemplo, podría ser el uso de archivos. Sin
embargo, un sistema informático que gestiona cantidades de
información importantes requiere de operaciones de manipu-
lación que sean rápidas, eficientes y flexibles. En este sentido,
las bases de datos relacionales ofrecen una forma simple,
flexible y rápida de recuperar, modificar y almacenar grandes
cantidades de datos. Es importante destacar que muchos
problemas que surgen en estas operaciones son resueltos por
el propio sistema de gestión de bases de datos, liberando al
programador de estas tareas.
• Un modelo de acceso a la información estándar. Una de las
ventajas más importantes de las bases de datos relacionales
es la de ofrecer un modelo estándar de organización y acceso
a la información. La organización de la información se basa
en el denominado modelo relacional, que la estructura en
términos de tablas formadas por filas y columnas. Esta forma
de organización resulta, por lo general, bastante intuitiva y
de fácil aplicación a la mayoría de los casos de persistencia de
información que se presentan. Asimismo, ofrece un mecanis-
mo estándar de acceso basado en un lenguaje de consultas
denominado SQL que tiene sus fundamentos en un modelo
formal denominado «álgebra relacional». La universalización
y estandarización de este lenguaje, hace que cualquier pro-
gramador que conozca el lenguaje estándar pueda utilizar
cualquier base de datos relacional con independencia del pro-
ducto comercial que la implemente (existen dialectos de SQL
e implementaciones que aumentan la sintaxis, pero todos los

17
© Editorial UOC Introducción a las bases de datos NoSQL

productos deben implementar la sintaxis nuclear del estándar


SQL).

Sin embargo, las necesidades en cuanto a persistencia de la


información cambiaron radicalmente con la aparición del big
data. Algunas de las necesidades que caracterizan este nuevo
contexto son:

• Necesidad de gestionar inmensas cantidades de datos. Por ejem-


plo, los datos que generan cada segundo los diferentes tipos
de sensores que se pueden encontrar en relojes inteligentes,
smartphones, sensores de contaminación, etc. Numéricamente,
superan a la capacidad habitual que gestionaban las bases de
datos relacionales de los sistemas de información anteriores al
big data.
• Necesidad de manipular datos muy heterogéneos que pueden
ser estructurados, semiestructurados o simplemente no pre-
sentar una estructura regular. Las bases de datos se caracte-
rizan precisamente por estar diseñadas para almacenar datos
que presentan una estructura regular acorde un esquema
definido. De hecho, el primer paso para crear una base de
datos relacional es definir su esquema, es decir, cómo van a
ser los datos que se van almacenar. Este esquema se supone
fijo y estable, permitiendo leves modificaciones a lo largo de
la vida de la base de datos. En este sentido, el diseñador espe-
ra encontrar una estructura fija y regular en los que se quiere
almacenar. Es por ello que para este nuevo contexto, el uso
de esquemas fijos no es una solución óptima pues tal como
se ha argumentado, los datos pueden ser estructuralmente
heterógeneos. Esto obligaría a estar realizando continuos
cambios en los esquemas de las bases de datos, introduciendo

18
© Editorial UOC Capítulo I. Introducción a las bases…

en muchos casos anomalías como, por ejemplo, la existencia


de filas con muchas columnas vacías, dado que para algunos
datos no tendrían sentido.
• Necesidad de un procesamiento eficiente de la información.
En el contexto del big data, la información debe ser pro-
cesada de forma conjunta, con rapidez, y si es posible en
tiempo real.
Esta necesidad se debe principalmente a que el resultado
del procesamiento permitirá tomar decisiones que tienen aso-
ciadas una ventaja económica (por ejemplo, en una empresa,
ofrecer un producto a un determinado tipo de usuario o
realizar una inversión de acuerdo al resultado de predicción
obtenida). Además, el resultado del procesamiento será más
fiable cuantos más datos se estén usando en este, razón por la
cual se requiere el procesamiento conjunto de toda la infor-
mación disponible.
En este sentido, las bases de datos relacionales tampoco
ofrecen una solución óptima para esta necesidad. En primer
lugar, presentan el denominado problema de la «impedancia»
de la información. Este problema se refiere a las diferentes
estructuras de datos utilizadas para almacenar la información
en los lenguajes de programación y en las bases de datos
relacionales. Estas últimas solo permiten almacenar aquella
información que se corresponde con tipos de datos básicos
tales como enteros, booleanos, reales, etc. Sin embargo, los
lenguajes de programación utilizan estructuras de datos más
complejas y ricas para el almacenaje, tales como pilas, colas y
otras. Esto genera un problema en el tránsito de la informa-
ción de las bases de datos a los programas, y viceversa, dado
que requiere de un proceso de traducción. Así, cada vez que
se quiere almacenar información desde un programa en una

19
© Editorial UOC Introducción a las bases de datos NoSQL

base de datos relacional habrá que descomponer la informa-


ción estructurada en los tipos de datos básicos definidos en el
esquema de aquella.
Igualmente, se produce el problema en sentido inverso
cuando se quiere almacenar información procedente de
un sistema de persistencia en una estructura de datos
de un programa. Si se considera que, en el contexto del
big data, el número de datos que se manipulan es enorme,
entonces estas operaciones de traducción suponen una carga
de trabajo que hacen muy ineficiente el uso de las bases de
datos relacionales. En segundo lugar, se tiene el problema del
escalado del procesamiento. Tal como se ha descrito ante-
riormente, el número de datos que es necesario gestionar en
el contexto del big data es enorme y tienen un crecimiento
exponencial. Esta situación influye directamente en las nece-
sidades en cuanto a capacidad de procesamiento de la infor-
mación de las herramientas utilizadas.
Esencialmente, existen dos formas de escalar la capaci-
dad de procesamiento: escalado vertical y escalado horizon-
tal. El escalado vertical se basa en el uso de máquinas con
capacidad de procesamiento cada vez más potentes. Así,
si una de ellas no cubre las necesidades de procesamiento,
lo que se hace es sustituirla por otra con mayor capacidad.
Esta solución no es económicamente muy rentable si el
tiempo durante el que se va a poder utilizar es pequeño,
situación que se da en este contexto. El crecimiento expo-
nencial de datos comentado con anterioridad hará que, en
un tiempo breve, la máquina quede obsoleta para las nuevas
necesidades.
El escalado horizontal se basa en conseguir las necesidades
de capacidad de procesamiento mediante la cooperación de un

20
© Editorial UOC Capítulo I. Introducción a las bases…

conjunto de máquinas que trabajan en paralelo, denominado


clúster, cuya suma de capacidades de procesamiento cubren
la requerida. Esta solución presenta como principal ventaja el
hecho de que es sostenible económicamente. Las máquinas
que se utilizan en un clúster normalmente son mucho más
baratas, pues presentan menos prestaciones que en el caso del
escalado vertical (no se pretende conseguir toda la necesidad
de procesamiento con una única máquina), de manera que
cuando se requiere más capacidad de procesamiento, basta
con añadir nuevas máquinas. En cualquier caso, económica-
mente, será más barato.
El uso del modelo de escalado horizontal también tiene
una implicación importante en cuanto a la organización de la
información. En el caso del escalado vertical, la información
se encuentra almacenada en la única máquina utilizada en este
modelo. Sin embargo, en el escalado horizontal, la informa-
ción se encuentra distribuida y replicada entre las diferentes
máquinas que forman el clúster, de manera que el procesa-
miento se realiza de manera distribuida. En este sentido, el
escalado horizontal ofrece otra característica no presente en
el escalado vertical, que es la alta fiabilidad.
Si se usa el escalado vertical y la máquina utilizada falla, el
sistema dejará de funcionar, dado que toda la información y
la capacidad de procesamiento se encuentra en esa máquina.
Sin embargo, en el escalado horizontal, si una máquina falla,
el sistema no tiene porque dejar de funcionar, dado que la
información se encuentra distribuida y replicada entre las
diferentes máquinas que forman el clúster. Esto asegura que
el sistema se mantendrá en funcionamiento en caso de averías
de elementos del clúster, haciéndolo independiente de las
máquinas concretas que lo forman.

21
© Editorial UOC Introducción a las bases de datos NoSQL

El principal problema que se presenta en cuanto al esca-


lado horizontal y su uso con bases de datos relacionales, es
que estas no están diseñadas para ejecutarse en clústers. Su
ejecución en este tipo de entornos presenta un gran número
de problemas difíciles de resolver tales como la implemen-
tación de operaciones de tipo JOIN, el aseguramiento de la
consistencia de la información ante operaciones concurren-
tes o la distribución de las filas de una tabla en las diferentes
máquinas del clúster. Aunque se han creado soluciones de
bases de datos relacionales para su ejecución en clúster, el
uso de las mismas ha demostrado que su rendimiento y efi-
ciencia no son demasiado buenos para este tipo de entornos
distribuidos.

Las limitaciones presentadas anteriormente propiciaron que


algunas empresas decidieran desarrollar sistemas alternativos al
modelo relacional que se ajustaran mejor a las nuevas necesida-
des impuestas por el fenómeno big data.
Concretamente fueron dos, Google y Amazon, las primeras
en proponer dos sistemas de almacenamiento de la informa-
ción basados en el uso de clústeres y que no seguían el modelo
relacional. Se trata de las bases de datos Big Tables de Google y
Dynamo de Amazon. Ambos casos permiten procesar grandes
cantidades de datos en ambientes distribuidos basados en el uso
de clústeres, y donde la información no se estructura de acuerdo
al modelo relacional.
Este primer hito supuso el punto de partida para el desarro-
llo de un conjunto de diferentes modelos de bases de datos que
tenían en común no utilizar el modelo relacional como apoyo
para organizar la información y en la mayoría de los casos estar
diseñadas para ejecutarse en entornos distribuidos.

22
© Editorial UOC Capítulo I. Introducción a las bases…

A estas bases de datos se las ha denominado bases de datos


NoSQL.
Resulta difícil hablar de tipos de bases de datos NoSQL
dado que los diferentes modelos propuestos no son puros, es
decir, comparten algunas características. Sin embargo, obvian-
do aquello que es común en todas ellas, existe una categori-
zación mayoritariamente aceptada de acuerdo al modelo de
organización de la información propuesto en las bases de datos
que diferencia los siguientes tipos:

• Bases de datos clave-valor: Riak, Redis, Dynamo, Voldemort.


• Bases de datos orientadas a documentos: MongoDB, CouchDB.
• Bases de datos basadas en columnas: Cassandra, Hypertable,
HBase, SimpleDB.
• Bases de datos de grafos: Neo4j, Infinite Graph.

3. Características comunes de las bases de datos


NoSQL

Tal como se comentaba en el punto anterior, las bases de


datos NoSQL presentan algunas características comunes tales
como:

• En la mayoría de los casos nacieron dentro del contexto de


proyectos de código abierto.
• El lenguaje de consultas que utilizan para recuperar la infor-
mación no es SQL. En muchos casos, son lenguajes adapta-
dos a la forma en que se encuentra organizada la información
(al diferir el modelo relacional basado en tablas con filas y

23
© Editorial UOC Introducción a las bases de datos NoSQL

columnas, no es aplicable el lenguaje SQL). Sin embargo, hay


algunas bases de datos NoSQL que han mantenido algunas
características de SQL como es el caso de la base de datos
Cassandra, que utiliza el lenguaje CQL que presenta algunas
similitudes con aquel.
• La mayoría de las bases de datos NoSQL están diseñadas
para ejecutarse en ambientes distribuidos basados en el uso
de clústeres de máquinas. Aunque no todas ellas cumplen esta
característica, como es el caso de las bases de datos orientadas
hacia grafos.
• Una característica común a las bases de datos NoSQL es su
aproximación a la consistencia de la información. Existe un
teorema denominado CAP que establece que si se consideran
las propiedades de consistencia de la información, su disponi-
bilidad y la tolerancia a la partición con respecto a la capa de
datos de un sistema de información, entonces solo es posible
que se mantengan dos de estas propiedades a la vez.
Esto significa que una capa de datos solo podrá pre-
sentar alguna de las siguientes combinaciones de propie-
dades: disponibilidad-tolerancia de partición (esta combi-
nación tiene que renunciar a la consistencia de la informa-
ción), disponibilidad-consistencia (esta combinación tiene que
renunciar a la tolerancia de partición que afectará la la cantidad
de datos que la capa de datos puede manejar) y tolerancia de la
partición-consistencia (esta combinación tiene que renunciar
a la disponibilidad).
En este sentido, un cambio importante en las bases de datos
NoSQL se refiere a la aproximación de la consistencia. En las
bases de datos relacionales se cumplían las propiedades ACID
(atomicity, consistency, isolation, durability). Estas propiedades repre-
sentan un sistema con una capa de datos que presenta consis-

24
© Editorial UOC Capítulo I. Introducción a las bases…

tencia-disponibilidad. Así, la atomicidad se refiere a que en una


transacción todas las operaciones se completan o ninguna será
completada; la coherencia se refiere a que la base de datos se
encontrará en un estado consistente durante el inicio y final
de una transacción y no puede dejar ese estado; el aislamiento
se refiere a que no habrá interferencia entre las transacciones
concurrentes y la durabilidad se refiere a que una vez que
se comprometa una transacción, los efectos de esta se man-
tendrán permanentes.
Sin embargo, en las bases de datos NoSQL se cumplen
las propiedades BASE (basically available, soft state, eventually
consistent ). Estas propiedades representan un sistema con una
capa de datos que presenta tolerancia a la partición-disponibi-
lidad. Así, básicamente disponible significa que garantiza una
respuesta a una solicitud incluso si los datos están obsoletos, el
estado flexible se refiere a que cuando se produce un cambio
en los datos en uno de los elementos del sistema donde se
encuentran replicados, los datos en el resto de réplicas no cam-
bian de forma síncrona, sino que este cambio se produce de
forma asíncrona, y eventualmente consistente se refiere a que
debido a la naturaleza distribuida de los nodos, puede ocurrir
que en un momento determinado el sistema no sea consistente
pero con el paso del tiempo se volverá consistente.
• Las bases de datos NoSQL no tienen un esquema fijo. Se trata
de una de las principales características que las diferencian de
las bases de datos relacionales.

En el mundo relacional, lo primero que hay que hacer antes


de crear una base de datos es definir el esquema de datos que
indica cómo van a estar organizados, qué tablas se necesitan,
qué columnas tiene cada tabla y qué tipo de datos son, y como

25
© Editorial UOC Introducción a las bases de datos NoSQL

se relacionan las diferentes tablas entre sí. Una vez definido el


esquema se pueden introducir los datos, pero no antes. El esque-
ma se podrá modificar levemente a lo largo de la existencia de
la base de datos aunque no es probable que sufra sufra muchas
variaciones, dado que se espera que los datos que se almacenen
sean uniformes y respondan a la organización representada en el
esquema.
Sin embargo, en el modelo NoSQL no existen esquemas,
sino que se pueden introducir directamente los datos y estruc-
turarse de diferentes formas (aunque siempre conforme al
modelo del tipo de base de datos NoSQL elegido). Cuando se
está en un ambiente en el que no se puede garantizar la uni-
formidad de los datos como es el caso del big data, el modelo
relacional basado en esquemas de definición estables es poco
óptimo, dado que para cada nuevo tipo de datos que no coin-
cida con la estructura inicial, habrá que ir adaptando de forma
dinámica el esquema.
El problema planteado tiene como consecuencia la introduc-
ción de anomalías tales como las denominadas tablas dispersas
(aquellas en las que existen muchas filas con columnas que con-
tienen valores nulos). Además, esta situación tiene consecuencias
directas sobre el mantenimiento propiamente dicho de la base
de datos. La no existencia de un esquema presenta tanto ventajas
como desventajas.
Una de sus principales ventajas es la flexibilidad, dado que se
adapta muy bien en proyectos en los que no se conoce a priori
toda la información que va a ser necesario almacenar o que
requiere poder ir cambiando estas necesidades de forma dinámi-
ca (tanto por adicción como por eliminación de información).
En este sentido, la no necesidad de esquema facilitará almacenar
en cada instante solo la información que se requiere.

26
© Editorial UOC Capítulo I. Introducción a las bases…

Como principal desventaja se tiene la necesidad que existe


en las aplicaciones de conocer determinadas características de la
estructura de los datos almacenados. Esto se refiere a los nom-
bres de los campos de información o los tipos de los datos. En el
modelo relacional, toda esta información se encontraba descrita
en el esquema de datos, de manera que las aplicaciones podían
acceder a este para consultarlo.
En un modelo sin esquemas, se hace necesaria la definición
de un esquema implícito en el código de las aplicaciones, donde
quedará reflejada esta información. Esto introduce una serie
de problemas. En primer lugar, el esquema implícito será muy
sensible a cambios que se produzcan en los datos almacenados
(cualquier cambio modificará a su vez el código de las aplica-
ciones que explotan esos datos). En segundo lugar, muchas de
las tareas que realiza el sistema de gestión de bases de datos
de forma transparente al programador tales como asegurar que
los datos introducidos cumplen una serie de requisitos (por
ejemplo que los datos eran de un tipo determinado), en un
sistema sin esquemas deben ser controladas directamente por
el programador a través del código. En tercer lugar, si se desea
conocer si existen determinados tipos de datos almacenados,
será necesario consultar el esquema implícito de la aplicación
(si el esquema implícito está bien estructurado será una tarea
fácil, de lo contrario puede ser una tarea bastante compleja). En
cuarto lugar, la no existencia de un esquema en la base de datos,
hace que la tarea de saber cuál es la mejor forma de recuperar o
almacenar los datos de una forma eficiente recaiga en el progra-
mador y no en el sistema de gestión de estas. En quinto lugar, la
no existencia de esquema, complica las tareas de validación de
los datos que se introducen y se modifican en sistemas en los
cuales varias aplicaciones están explotando los mismos datos.

27
© Editorial UOC Introducción a las bases de datos NoSQL

Esta tarea recae nuevamente en el programador. Además, en


este último caso, aparece un peligro adicional que es el cambio
del propio esquema de organización de la información.
Tal como se ha argumentado anteriormente, en los modelos
sin esquemas, aparecen esquemas implícitos en los códigos de
las aplicaciones que explotan los datos. Así, si varias aplicacio-
nes explotan los mismos datos, podría ocurrir que los cambios
producidos por una de ellas al añadir o eliminar datos influyeran
directamente en los esquemas implícitos definidos en el código
de las otras aplicaciones. El control de esta situación se vuelve
complejo, pues habría que controlar que los cambios que realizan
cada aplicación no afecta a las restantes.
Esencialmente, se puede concluir que el principal cambio que
se produce del uso al no uso de esquemas de definición de la
información es la traslación de responsabilidades. Así, muchas de
las tareas que los sistemas de gestión de bases de datos realizaban
de forma transparente al programador, ahora serán responsabi-
lidad de este. Como contrapartida, el programador consigue fle-
xibilidad en cuanto al tipo de información que puede almacenar,
libertad para realizar cambios en la estructura de la información
que almacena, y la garantía de almacenar solo aquella informa-
ción que necesita en cada momento.

4. Bases de datos NoSQL orientadas hacia


agregados

Los tipos de bases de datos NoSQL orientadas a documen-


tos, a familias de columnas y las de tipo clave-valor comparten
un modelo general de datos (aunque después cada una de ellas

28
© Editorial UOC Capítulo I. Introducción a las bases…

presente sus diferencias que las hacen particulares). En este sen-


tido, se habla de bases de datos orientadas hacia agregados. Un
agregado, desde el punto de vista de la información, está forma-
do por datos con diferente complejidad estructural, así pueden
contener listas u otras estructuras más elaboradas como registros
relacionados de información.
Desde el punto de vista de la manipulación de los datos y la
gestión de la consistencia de la información, la base de datos
tratará a los agregados como la unidad mínima de información
que es capaz de gestionar. En este sentido, las operaciones que
se realicen sobre un agregado serán atómicas y, de hecho, la inte-
racción con la base de datos se realiza en términos de agregados
(se generan y consumen agregados en cada operación con la base
de datos).
Realmente, este concepto de agregación no es del todo nuevo,
dado que también se encuentra presente en las bases de datos
relacionales. En ellas, el agregado estaría constituido por las filas
de la tabla que almacenan la información y, de hecho, la base
datos interacciona consumiendo y generando filas. Sin embargo,
existen algunas diferencias:

1) En primer lugar, la complejidad estructural de la informa-


ción que es capaz de almacenar una fila frente a un agregado.
La fila es una colección de valores de tipos básicos, y no admite
estructuras de información complejas tales como listas, registros
o anidamiento de información.
2) Las filas de una tabla, en general, están relacionadas con
filas de otras tablas. En el caso de los agregados, aunque pudie-
ran existir relaciones con otros agregados, estas no son explí-
citas y no impiden que cada uno se pueda manipular de forma
independiente.

29
© Editorial UOC Introducción a las bases de datos NoSQL

Este hecho tiene implicaciones importantes en cuanto a la


ejecución de las bases de datos en entornos distribuidos basados
en el uso de clústeres. En este sentido, el concepto de agregado
es utilizado como la unidad que se distribuye y se replica en
los nodos de un clúster de máquinas, puesto que tal como se
ha comentado, es autocontenido e independiente del resto de
agregados.
Se puede observar que esto no ocurre con las filas, puesto que
las relaciones de dependencia que existen entre filas de diferentes
tablas harían necesario tenerlas en cuenta cuando se distribuyera
y se replicara la información.
3) En general, la estructura de la información que se almacena
no se corresponde con una fila de una tabla. En muchos casos,
la información que se desea modelar para almacenar en una base
de datos, no se corresponde con una colección de datos de tipos
básicos (que es lo que representa una fila), sino que se correspon-
de con un conjunto de datos que están estrechamente relaciona-
dos mediante estructuras complejas de información.
Este hecho tiene dos implicaciones importantes. Por una
parte, si se utiliza el modelo relacional para almacenar la informa-
ción, el diseñador debe realizar un proceso de descomposición de
esta para eliminar la estructura que presentan los datos y poderla
describir en términos de tuplas de datos básicos, perdiendo las
relaciones directas entre ellos. Estas relaciones se reconstruyen
mediante las dependencias que existen entre las tablas que for-
man la base de datos, aunque no son explícitas. Sin embargo, en
el caso de los agregados, la modelización es prácticamente direc-
ta, pues al admitir una mayor riqueza de estructuras de datos de
diferente complejidad para almacenar la información, se facilita
el proceso de almacenamiento de la información sin tener que
descomponerla.

30
© Editorial UOC Capítulo I. Introducción a las bases…

La segunda implicación que tiene este hecho se centra en el


tipo de consultas que se facilitan cada modelo. En el caso del
modelo relacional, la descomposición de la estructura de la infor-
mación, y el ocultamiento de las relaciones directas, hacen que la
información se represente de una forma neutral que facilita rea-
lizar consultas de cualquier tipo. Los datos no están preparados
para consultarse de una forma concreta, si no que pueden ser
consultados de diversas formas al no estar atados por las estruc-
turas que los relacionaba. En cambio, en un modelo orientado
hacia agregados, las dependencias de información se mantienen
intactas, influyendo en el tipo de consultas que se pueden reali-
zar. Así, habrá consultas que se podrán hacer de una manera más
óptima que otras. Es por ello que, desde el punto de vista del
diseño de una base de datos, se deben desarrollar los agregados
pensando en el tipo particular de consulta que se va a realizar
(con el objetivo de facilitar ese tipo de consulta). Otra implica-
ción directa de este hecho, es que en un modelo de agregados
habrá tantos tipos como tipos de consultas diferentes se quieran
realizar. No se espera resolver todos los tipos de consultas con
un único tipo de agregado. En cambio, en el modelo relacional
con un único modelo se pueden resolver todas las consultas que
se deseen (la dificultad de realizar una consulta se traslada a la
dificultad de crear la sentencia SQL correspondiente).
Con el objetivo de fijar ideas y poder comparar ambas apro-
ximaciones, se va a mostrar un ejemplo de modelización. Así,
considérese que se desea almacenar información de los clientes
de un banco y de los productos que tienen contratados. De un
cliente se desean mantener los datos personales tales como nom-
bre, apellidos, dirección, DNI, correo electrónico, etc. Asimismo
se desea conocer información sobre las sucursales del banco con
las que opera (normalmente será una pero podría darse el caso de

31
© Editorial UOC Introducción a las bases de datos NoSQL

que fuera más de una). Por último, se desea conocer información


de todos los productos financieros que mantiene contratados
con el banco tales como tipo de producto, cantidad de dinero
asociada, plazos y sucursal en la que se ha contratado.
La información descrita podría modelarse tanto usando un
modelo relacional como usando un modelo orientado hacia
agregados. En el primer caso, haciendo un análisis simplista de la
información que se desea modelar, probablemente serían nece-
sarias las siguientes tablas. Una tabla para almacenar los datos
personales de cada cliente, otra para almacenar las direcciones,
dado que habría que contemplar el caso de que un cliente tuviera
varios domicilios, una tabla para almacenar la información de
una sucursal y una última para almacenar los productos financie-
ros contratados por los clientes. Este último caso, tendría diseños
alternativos como, por ejemplo, tablas diferentes por cada tipo
de producto que ofrece el banco, de manera que cada una solo
contuviera específicamente la información de los clientes que
han contratado determinado producto.
Tal como se puede observar en este modelo, las relaciones de
agregación entre los datos han desaparecido, se tienen por un
lado todos los datos personales, por otro lado las direcciones,
etc. En este sentido, para mantener relacionada la información en
cada una de las tablas antes mencionadas, será necesario introdu-
cir en cada una de ellas columnas que representen claves ajenas.
Sin embargo, el tipo de relación que permite establecer las claves
ajenas entre los datos no permite diferenciar entre relaciones de
agregación de información y entre relaciones de información
que no son de agregación (se puede deducir, por ejemplo, que
un cliente tiene asociadas una o más direcciones, o que un clien-
te tiene relación con una o más sucursales, pero no se puede
reconstruir como es la agregación original de la información).

32
© Editorial UOC Capítulo I. Introducción a las bases…

En este sentido, se dice que las bases de datos relacionales son


ignorantes de las agregaciones. La principal implicación es que el
desconocimiento de cómo se encuentra agregada la información
dificulta la distribución de los datos, pero sin embargo, permite
ver los datos desde diferentes perspectivas. Por tanto es una
buena elección cuando se conoce a priori como se va a consultar
la información.
Si se optara por modelar el problema usando agregados,
existirían varios tipos de soluciones. Así, una posible solución
sería considerar dos tipos de agregados: clientes y productos.
Un agregado «cliente» podría almacenar los datos personales, las
direcciones del cliente, la información de las sucursales en las que
tiene productos contratados, así como una lista de estos produc-
tos con las particularidades de cada contrato (dinero contratado
en el producto, fecha de apertura, sucursal donde se contrató,
etc). Y un agregado «producto» podría almacenar toda la infor-
mación de un producto contratado por un cliente concreto, es
decir, datos personales, direcciones del cliente, sucursal donde se
contrató… así como toda la información particular del producto
contratado (dinero invertido, fecha de apertura, etc).
Conviene observar varios aspectos acerca de este diseño. En
primer lugar, este permite la repetición de datos (así, por ejemplo,
los datos personales o la información de las sucursales se repiten
en ambos agregados, situación que no se daría en un modelo rela-
cional). En segundo lugar, la estructura de cada agregado influye
directamente en el tipo de consulta que facilita. Así, por ejemplo,
si se consideran los agregados de tipo cliente, la consulta natural
que facilita podría ser recuperar todos los productos que tiene con-
tratado un cliente en el banco, o recuperar todas las sucursales en
las que tiene contratado un producto financiero. De igual forma,
el agregado «producto» permite recuperar fácilmente información

33
© Editorial UOC Introducción a las bases de datos NoSQL

sobre un producto concreto contratado por un cliente en parti-


cular. Sin embargo, si se plantean consultas como, por ejemplo,
recuperar toda la información de los clientes que han contratado
un tipo concreto de producto financiero o recuperar toda la infor-
mación de los clientes que han contratado algún producto en una
sucursal determinada, el proceso de obtención del resultado no se
podría hacer consultando un único agregado.
Ambos casos requieren realizar un recorrido por cada uno de
los agregados para obtener la información correspondiente, lo cual
en términos computacionales lo hace ineficiente (esencialmente
habría que hacer un bucle donde se fuera comprobando en cada
agregado si un cliente ha contratado o no el producto).
Esto no quiere decir que no se pueda resolver ese tipo de
consultas con un modelo de agregación, sino que cada agregado
está preparado para facilitar un tipo de consulta concreta. Así, las
consultas planteadas con anterioridad se podrían resolver crean-
do un agregado con la estructura de la información adecuada
para la consulta (es decir, un agregado de tipo «producto» que
contuviera la información de todos los clientes que han contra-
tado ese tipo de producto, de forma que en una única consulta
del agregado se recuperaría la información buscada).
En el modelo por agregación es necesario saber previamen-
te cómo se van a realizar las consultas, de forma que estos se
puedan diseñar para facilitarlas. No existe un único modelo de
agregación que cubra todas las posibles consultas, o un modelo
mejor que otro, todos son válidos, pero cada uno será adecuado
para un caso concreto de acceso a la información. Asimismo,
hay que tener en cuenta que los agregados tienen un significado
asociado con respecto a la forma en la que las aplicaciones los
utilizan que va más allá de posibles relaciones lógicas que puedan
existir entre los datos. Por otro lado, es importante destacar que

34
© Editorial UOC Capítulo I. Introducción a las bases…

el modelo de agregación facilita la ejecución de una base de datos


en un clúster, dado que representa la información que debe ser
manipulada de forma conjunta y que, por tanto, deberá encon-
trarse en una misma máquina. Es decir, los agregados ayudan a
diseñar la estructura del clúster.
Por último, hay que tener presentes las necesidades de atomi-
cidad de las operaciones que se realizan. En este sentido, en estos
modelos solo es posible asegurar la atomicidad a nivel de agrega-
dos (si es necesario hacerlo sobre múltiples agregados entonces
habrá que hacerlo vía código). Es por ello que un criterio de
diseño de los agregados serán las necesidades de atomicidad de
las operaciones que tengan que realizarse sobre la información.

5. Bases de datos NoSQL documentales

Las bases de datos documentales son un tipo de base de datos


orientada hacia agregados donde el agregado es una estructura
que se denomina genéricamente documento. Un documento es
equivalente a alguna de las estructuras de datos que existen en
los lenguajes de programación tales como registros, diccionarios,
o tablas hash. En este sentido, ofrece una gran versatilidad para
almacenar muchos de tipos de datos.
Los documentos y sus contenidos se pueden manipular
mediante lenguajes de consultas similares a SQL. De esta forma
se pueden crear consultas en base a condiciones sobre el conte-
nido del documento, y recuperar partes del mismo. Asimismo,
es posible definir índices basados en su contenido.
Sin embargo, presenta limitaciones en cuanto a los tipos y
estructuras de datos almacenar. Así, los documentos solo admi-

35
© Editorial UOC Introducción a las bases de datos NoSQL

ten un conjunto determinado de tipos de datos, por lo que para


almacenar otros, habrá que adaptarlos o transformarlos.
A nivel de concurrencia y consistencia de los datos, solo se
garantiza la atomicidad de las operaciones a nivel de agregado.
Por tanto para garantizar la atomicidad entre varios agregados es
necesario realizarlo directamente desde el código.
Por último, cabe mencionar que este tipo de bases de datos
están relacionadas con las bases de datos de tipo clave-valor,
dado que una base de datos documental puede llegar a compor-
tarse como una base de datos de este otro tipo. Una de las prin-
cipales diferencias entre unas y otras es la opacidad del agregado.
En el caso documental, se puede acceder al contenido de la agre-
gado, sin embargo en el caso clave-valor, el agregado permanece
oculto.

6. Bases de datos NoSQL de tipo clave-valor

Se trata de un tipo de base de datos orientada hacia agregados


cuya principal característica es que el agregado que gestiona puede
ser de cualquier tipo, pero las únicas operaciones de manipulación
permitidas son el almacenamiento y recuperación de este.
En este sentido, no es posible consultar el contenido almace-
nado en el agregado desde el interior de la base de datos (no se
pueden construir consultas en base a la estructura de la informa-
ción), de manera que para acceder al contenido hay que hacerlo
desde fuera.
Por otro lado, el almacenamiento de la información se realiza
utilizando un mecanismo de tipo clave-valor semejante a algunas
estructuras de datos presentes en los lenguajes de programación

36
© Editorial UOC Capítulo I. Introducción a las bases…

tales como diccionarios o tablas hash. Así, a cada agregado que se


quiere insertar en la base de datos, se le asocia una clave que
sirve para poder recuperarlo posteriormente. En este sentido,
cualquier operación de búsqueda y recuperación se basa exclusi-
vamente en la clave que tiene asociado cada agregado, y lo que se
recupera son agregados completos.1
Las bases de datos documentales pueden comportarse como
bases de datos de tipo clave-valor, puesto que se pueden crear
consultas para recuperar un documento utilizando únicamente
el identificador de este como si fuera una clave y sin utilizar res-
tricciones basadas en los contenidos almacenados. Sin embargo,
estos modelos difieren en la forma de gestionar los agregados.
En las bases de datos de tipo clave-valor, el contenido del agre-
gado es opaco e inaccesible, lo que impide construir consultas
usando los contenidos de los agregados (no se pueden establecer
condiciones de recuperación en base al contenido o estructura
del agregado). En cambio en las bases de datos documentales se
puede acceder al contenido y estructura del agregado, y por tanto
se pueden construir consultas en forma de restricciones sobre los
contenidos de estos.
Conviene observar que la opacidad del agregado hace que
no sea necesario realizar transformaciones de la información
ni para almacenarlo ni para recuperarlo, lo que facilita por una
parte la distribución de los agregados en un clúster y, por otra

1 Esto no sucede en todas las bases de datos orientadas hacia agregados, así, por
ejemplo, en las bases de datos documentales, las consultas se construyen utilizan-
do los campos de información y el contenido de los agregados, y se recuperan
como resultado partes de un agregado.

37
© Editorial UOC Introducción a las bases de datos NoSQL

parte, hace no se presente el problema de la impedancia en este


modelo.2
Por último, hay que mencionar que dentro de las bases de
datos de tipo clave-valor se pueden encontrar casos particulares
tales como aquellas que ofrecen soporte para realizar consultas
sobre los agregados usando herramientas externas de búsqueda
u otras que permiten reestructurar los datos que se almacenan en
el agregado aunque este sea opaco.

7. Bases de datos NoSQL orientadas a columnas

En el modelo relacional, las filas se utilizan como unidad de


almacenamiento porque aumentan el rendimiento de las escritu-
ras. Sin embargo, en situaciones en las que no se van a realizar
muchas escrituras y lo que se requiere son lecturas de determi-
nadas columnas con muchas filas a la vez, es más óptimo utilizar
como unidad de almacenamiento grupos de columnas que con-
tienen las filas que deben ser leídas.
Esta unidad de almacenamiento se denomina «familias de
columnas», y las bases de datos que lo implementan se deno-
minan «bases de datos orientadas hacia columnas». Por tanto, el
modelo subyacente a este tipo de bases de datos se fundamenta
en almacenar datos en columnas en vez de en filas. Cada columna
tiene que ser parte de una única familia, y la columna actúa como

2 La opacidad de la información constituye una ventaja si se compara con las


bases de datos documentales donde existen limitaciones (impuestas por las
estructuras de datos admitidas por el modelo) en cuanto a la información que
puede ser almacenada. Por otro lado, estas limitaciones ofrecen como ventaja la
flexibilidad en el acceso a la información.

38
© Editorial UOC Capítulo I. Introducción a las bases…

la unidad de acceso, partiendo del hecho de que a los datos para


una familia de columnas particular se accederá normalmente de
manera conjunta.
Observemos que este modelo puede entenderse como una
estructura agregada a dos niveles donde la primera clave es un
identificador de fila que permite acceder a un agregado de segun-
do nivel, que es lo que se denominan columnas. El acceso a la fila
es completo, pero existen operaciones que permiten seleccionar
una columna particular.

39
© Editorial UOC Introducción a las bases de datos NoSQL

Bibliografía
Mohamed, M. A.; Altrafi, O. G.; Ismail, M. O. (2014). «Relational
vs. NoSQL Databases: A Survey». International Journal of Computer and
Information Technology (vol. 3, págs. 598-601).
Moniruzzaman, A. B. M.; Hossain, S. A. (2013). «NoSQL Database:
New Era of Databases for Big Data Analytics-Classification,
Characteristics and Comparison» [artículo en línea]. ArXiv.org http://
cort.as/-F2Pl.
Pramod, J. S.; Fowler, M. (2012). NoSQL Distilled: A Brief Guide to the
Emerging World of Polyglot Persistence. Addison-Wesley Professional.
Redmond, E.; Wilson, J. R. (2012). Seven databases in seven weeks: a guide to
modern databases and the NoSQL movement. Pragmatic Bookshelf.
Tiwari, S. (2011). Professional NoSQL. John Wiley & Sons.
Vaish, G. (2013). Getting started with NoSQL. Packt Publishing Ltd.

40
© Editorial UOC Capítulo II. Introducción a Redis

Capítulo II
Introducción a Redis.
Una base de datos NoSQL de tipo clave-valor

1. Introducción

Tal como se ha comentado en el capítulo anterior, el modelo


de datos de tipo clave-valor se clasifica dentro de los modelos
orientados hacia agregados. En particular, en este modelo,
los agregados son estructuras de información opacas dado que
sus datos no son accesibles desde la base de datos, únicamente
se pueden almacenar o recuperar como una unidad, utilizando
una clave asociada a estos. Así, para poder acceder a los con-
tenidos, hay que hacerlo fuera de la base de datos. Entre sus
ventajas, se encuentra el hecho de que no sea necesario realizar
transformaciones de la información para almacenar o para recu-
perar el agregado, y, como inconvenientes, el hecho de no poder
recuperar trozos concretos de un agregado. Asimismo, no es
posible establecer consultas en base al contenido del agregado
propiamente dicho.
Redis (Remote Dictionary Server) es una base de datos
NoSQL de tipo clave-valor creada en el año 2006 por Salvatore
Sanfilippo. Ha sido utilizada por grandes compañías como
Twitter, GitHub, Tumblr, Pinterest, Instagram, Hulu, Flickr, o
The New York Times.
En este capítulo se realiza una introducción a los conceptos
básicos y la terminología fundamental necesaria para poder enten-
der qué es una base de datos en Redis y qué elementos la forman.

41
© Editorial UOC Introducción a las bases de datos NoSQL

En este sentido, se describen sus principales características y las


nociones básicas para poder empezar a trabajar con ella.

2. Principales características

Algunas de las principales características presentes en Redis


son:

• Redis es una base de datos que almacena toda la información


en la memoria pero con persistencia en el disco, lo cual le
facilita una alta velocidad de escritura y lectura (la mayoría de
las veces se ejecutan en milisegundos). Sin embargo, esta con-
figuración impone una limitación en cuanto a los conjuntos
de datos que puede almacenar, puesto que no pueden ser más
grandes que la memoria. Para gestionar la memoria se utiliza
la memoria virtual que mantiene todas las claves pero solo
escribe los valores menos usados recientemente en el disco. La
persistencia en el disco se puede realizar de dos formas, bien
realizando una copia de los datos en un archivo binario (snap-
shotting) o bien en un archivo de solo anexos (AOF, append-only
file) que contiene todos los comandos ejecutados o cambios
realizados sobre los datos (journaling).
• Otra ventaja de almacenar toda la información en memoria
es que la representación en memoria de estructuras de datos
complejas es mucho más sencilla de manipular en compara-
ción con la misma estructura de datos en el disco.
• En Redis se utiliza una arquitectura maestro-esclavo para la
implementación de un clúster, y se realiza una réplica asíncro-
na de los datos. En este sentido, todos los datos del maestro

42
© Editorial UOC Capítulo II. Introducción a Redis

se copian de forma asíncrona en los nodos esclavos del clús-


ter, de modo que si el nodo maestro fallara, entonces uno
de los nodos esclavos puede ser promovido a nodo maestro.
Además, se consigue una lectura eficiente dado que se puede
repartir entre los nodos esclavos. Conviene observar que la
réplica de los datos se puede hacer sobre cualquier número de
nodos esclavos del clúster.
• Tal como se ha comentado, Redis utiliza una arquitectura
maestro-esclavo, de manera que las actualizaciones se realizan
sobre el nodo maestro del clúster (y se expanden al resto de
nodos de forma asíncrona) y los nodos esclavos se utilizan
solo en modo lectura. Así, puede ocurrir que el nodo maestro
existan nuevos elementos escritos, pero al leer de un nodo
esclavo se estén leyendo valores obsoletos dado que no se
han actualizado aún. En este sentido, el retraso al realizar la
actualización produce una inconsistencia momentánea. Por
esta razón se dice que Redis ofrece una consistencia de tipo
eventual.
• Las operaciones en Redis son atómicas, lo cual asegura que
si hay dos clientes accediendo concurrentemente, el servidor
recibirá el valor actualizado.
• Con el objetivo de conseguir un equilibrio en la carga de traba-
jo, se usa el nodo maestro para escribir los datos y se usan los
esclavos para leer los datos. Asimismo, las solicitudes de lectura
se distribuyen de forma uniforme entre los nodos esclavos.
• Se creó como un proyecto de código abierto con licencia
BSD. Está implementada utilizando C optimizado y permite
ser gestionada por una gran variedad de lenguajes de progra-
mación.
• Permite el almacenamiento en memoria de casi cualquier tipo
de datos con el objetivo de facilitar el uso de las estructuras de

43
© Editorial UOC Introducción a las bases de datos NoSQL

datos más adecuadas para almacenar cada tipo de contenidos,


en vez de obligar a usar una única estructura de datos que no
tiene porqué ser la mejor para todos los casos.
En este sentido, admite una gran variedad de tipos de
datos comparado con otras bases de datos de tipo clave-valor
tales como cadenas, listas, conjuntos sin ordenar, conjuntos
ordenados o HyperLogLogs. Además muchos de los tipos de
datos utilizados son equivalentes a los utilizados en los lengua-
jes de programación lo que facilita el mapeo de los contenidos
entre los programas y la base de datos.
• Dispone de herramientas del tipo Publicador/Suscriptor para
publicar mensajes en canales que se entregan a suscriptores
(esta característica viene bien para implementar sistemas de
chat y mensajería), claves de tipo TTL en las que se puede
configurar un tiempo de vida determinado tras el que se eli-
minan a sí mismas (esta característica resulta especialmente
útil para mantener limpias las bases de datos), un sistema de
transacciones y contadores, contadores atómicos que garan-
tizan que las condiciones de la carrera no creen resultados
incoherentes. Asimismo, se dispone de un lenguaje de scripts
denominado Lua que permite la creación de nuevas funciones
y operaciones sobre Redis.
• Redis ha sido aplicado en diversos ámbitos tales como la crea-
ción de cachés de alto rendimiento para una base de datos,
administración de sesiones de aplicaciones web usando claves
TTL, creación de clasificaciones dinámicas usando conjuntos
ordenados, implementación de colas, listas circulares o la acti-
vación de eventos publicados.

44
© Editorial UOC Capítulo II. Introducción a Redis

3. Instalación de Redis

En la figura 1 se puede observar la página principal del pro-


yecto Redis. Como la mayoría del software, este se encuentra suje-
to a constantes cambios por la aparición de nuevas versiones o
actualizaciones donde se corrigen errores y se introducen nuevas
funcionalidades. Con el objetivo de mostrar los contenidos del
capítulo, se va a utilizar la versión más estable de Redis actual-
mente, la versión 5.0.3. (los pasos de instalación y ejecución son
similares para cualquiera de las versiones).

Figura 1. Página principal de Redis

Fuente: captura de sitio web https://redis.io/

Para realizar la instalación de Redis, se deben seguir los


siguientes pasos:

• Una vez conectado a la página que contiene todas las versio-


nes de Redis (figura 2). (http://download.redis.io/releases/),
se pulsa sobre el enlace que indica la versión 5.0.3.

45
© Editorial UOC Introducción a las bases de datos NoSQL

Figura 2. Descarga del paquete de Redis

Fuente: captura de sitio web https://redis.io/

• Se abre un terminal de comandos de Linux y se navega hasta


el directorio que contiene el paquete descargado y se ejecuta:
tar xzvf redis-5.0.3.tar.gz, para descomprimir el paquete
(figura 3).

Figura 3. Descomprensión del paquete de Redis

Fuente: elaboración propia

46
© Editorial UOC Capítulo II. Introducción a Redis

• Se navega hasta dentro de la carpeta descomprimida y se eje-


cuta el comando sudo make install (figura 4).

Figura 4. Paquete descomprimido de Redis

Fuente: elaboración propia

Una vez que se ha instalado Redis, para poder trabajar con la


base de datos, es necesario lanzar dos programas desde la carpe-
ta src que son redis-server y redis-cli (figura 5). Redis-server es
el servidor de Redis y puede ejecutarse en modo unitario o en
clúster, y redis-cli es el cliente que permite interactuar con Redis
a través de una línea de comandos (se introducen los comandos
y se ejecutan). El servidor de Redis se ejecuta por defecto en el
puerto 6379.

47
© Editorial UOC Introducción a las bases de datos NoSQL

Figura 5. Cliente y servidor de Redis

Fuente: elaboración propia

Para lanzar cada programa se abre un terminal del sistema,


y situándose en la carpeta src de Redis, se escribe el nombre de
cada programa (figura 6).

Figura 6. Ejecución de redis-cli y redis-server

Fuente: elaboración propia

48
© Editorial UOC Capítulo II. Introducción a Redis

Para trabajar con los ejemplos que se van a presentar en las


secciones siguientes, se debe ejecutar el servidor de Redis, y los
comandos se deberán introducir a través del cliente de Redis.

4. Bases de datos en Redis

Redis es una base de datos de tipo clave-valor que almacena


conjuntos de datos denominados valores que pueden ser de dife-
rentes tipos. Cada base de datos se identifica mediante un núme-
ro (por defecto toma el valor de 0), y se puede cambiar entre
ellas utilizando el comando SELECT. En la figura 7 se muestra
un ejemplo en el que se cambia de la base de datos por defecto
a la base de datos 1, y viceversa.

Figura 7. Cambio de base de datos

Fuente: elaboración propia

Otro comando muy útil relacionado con las bases de datos es


FLUSHDB que reinicia una base de datos a su estado original y
la deja limpia.
Al ser una base de datos de tipo clave-valor, cada conjunto de
datos tiene asociado una clave que sirve para identificarlo. Por
ejemplo, si se quiere almacenar un valor que es de tipo cadena se
pueden usar los comandos SET y GET que permiten respectiva-
mente asociar una clave a un valor de tipo cadena y recuperar el

49
© Editorial UOC Introducción a las bases de datos NoSQL

valor a partir de la clave. En el ejemplo de la figura 8 se muestra


la creación de una clave y la recuperación del valor asociado.

Figura 8. Creación de un par clave-valor y recuperación del valor

Fuente: elaboración propia

Una diferencia importante de Redis con respecto a otras


bases de datos es la imposibilidad de plantear consultas sobre
el contenido de los valores asociados a una clave. El contenido
de los valores permanece oculto para Redis. En este sentido,
las claves son tratadas como elementos de primer orden, dispo-
niendo para ellas de una gran variedad de posibles operaciones.
En cambio, los valores son elementos secundarios que solo se
almacenan.
En Redis, todos los datos se almacenan en memoria, existen
varias formas de gestionarla. La primera consiste en realizar
copias periódicas en disco de todo lo que hay almacenado
teniendo en cuenta las claves que hayan cambiado. Para ello se
usan directivas de la forma «Si N claves han cambiado enton-
ces almacenar la base de datos cada T segundos» (de hecho,
por defecto, existe una directiva que indica que se debe alma-
cenar la base de datos cada 60 segundos si se han producido
cambios en 1000 o más claves). Otro mecanismo consiste en
actualizar un archivo en el que cada vez que una clave cambia,
se actualiza solamente lo que haya cambiado. Por último, otra
opción consiste en gestionar la persistencia utilizando un nodo
esclavo.

50
© Editorial UOC Capítulo II. Introducción a Redis

Tal como se señalaba más arriba, las claves tienen asociado un


conjunto de comandos. La invocación de los comandos sigue la
misma sintaxis:

Nombre_Comando Nombre_clave

A continuación, se van a comentar algunos de los comandos


más utilizados. Primero nos centraremos en el comando KEYS, el
cual devuelve todas las claves almacenadas en la base de datos que
encajan con un patrón dado. En el ejemplo de la figura 9 se mues-
tra la invocación del comando KEYS con el símbolo *, que repre-
senta cualquier valor, de manera que devuelve como resultado
todas las claves almacenadas en ese momento en la base de datos.

Figura 9. Uso del comando KEYS

Fuente: elaboración propia

Los comandos SETEX, EXPIRE y EXPIREAT están relacio-


nados con el tiempo de vida de una clave. Así, EXPIRE permite
especificar un tiempo de expiración para una clave en segundos,
pasado el cual, la clave se elimina. La ejecución del comando
retornará bien 1, si se ha asociado correctamente, o bien 0 si la
clave indicada no existe o no se puede asociar el tiempo de expi-
ración. Un comando relacionado con este último es el comando
TTL. Cuando se aplica sobre una clave puede devolver como
resultado un valor positivo que representa el tiempo que le queda
de vida, el valor -2 si la clave ya ha expirado o no existe, o bien el
valor -1 si la clave existe pero no tiene asociado un valor de expi-
ración. En la figura 10 se muestra el uso del comando EXPIRE

51
© Editorial UOC Introducción a las bases de datos NoSQL

y del comando TTL sobre una clave a la que se le ha asociado un


tiempo de expiración 10.

Figura 10. Uso del comando EXPIRE Y TTL

Fuente: elaboración propia

De forma similar a los casos anteriores, se tiene el comando


SETEX, que realiza de forma atómica las operaciones de crear
y asociar un tiempo de expiración a una clave dada, y el coman-
do EXPIREAT que actúa de la misma forma que el comando
EXPIRE pero en vez de asociar a la clave un tiempo en segun-
dos, le asocia un valor que representa el tiempo transcurrido
desde el 1 de Enero de 1970.
Por último, hay que observar que las limitaciones que exis-
ten para realizar consultas sobre los contenidos de los valores
almacenados, la forma en la que se almacena la información y el
tipo de estructuras que ofrece la base de datos para gestionar los
diferentes datos, influye en la alta velocidad de procesamiento
que ofrece este producto. En particular, existe un comando en
Redis, redis-benchmark, que permite medir el rendimiento del
sistema en operaciones por segundo. En la figura 11 se muestra
una invocación del mismo, y el resultado que se obtiene.

52
© Editorial UOC Capítulo II. Introducción a Redis

Figura 11. Invocación de redis-benchmark para medir el rendimiento de Redis

Fuente: elaboración propia

En la tabla 1 se muestran algunos de los comandos más


importantes definidos sobre las claves.

Tabla 1. Comandos asociados a las claves

Nombre del comando Significado

DEL key Elimina la clave si existe.

DUMP key Retorna una versión serializada del valor


almacenado asociado a la clave indicada.

EXISTS key Comprueba si la clave existe o no.

EXPIRE key seconds Configura el tiempo de expiración de una clave


después del tiempo especificado en segundos.

EXPIREAT key timestamp Configura el tiempo de expiración de una clave


después del tiempo especificado en formato
time stamp de Unix.

PEXPIRE key milliseconds Configura el tiempo de expiración de una clave


en milisegundos.

PEXPIREAT key milliseconds- Configura el tiempo de expiración de una


timestamp clave después en formato time stamp de Unix
especificado en milisegundos.

KEYS pattern Encuentra todas las claves encajando con el


patrón específicado.

53
© Editorial UOC Introducción a las bases de datos NoSQL

Nombre del comando Significado

MOVE key db Mueve una clave a otra base de datos.

PERSIST key Elimina el tiempo de expiración de una clave.

PTTL key Obtiene el tiempo restante en claves que


expiran medido en milisegundos.

TTL key Obtiene el tiempo restante en claves que


expiran.

RANDOMKEY Retorna una clave aleatoriamente de la base de


datos.

RENAME key newkey Renombra la clave dada con el nuevo nombre


de clave.

RENAMENX key newkey Renombra la clave dada con el nuevo nombre


de clave, en caso de que no exista ese nombre.

TYPE key Retorna el tipo de datos del valor almacenado y


asociado a la clave.
Fuente: elaboración propia

54
© Editorial UOC Capítulo II. Introducción a Redis

Bibliografía
Carlson, J. L. (2013). Redis in action. Manning Publications Co.
Da Silva, M. D.; Tavares, H. L. (2015). Redis Essentials. Packt Publishing
Ltd.
Das, V. (2015). Learning Redis. Packt Publishing Ltd.
Macedo, T.; Oliveira, F. (2011). Redis Cookbook: Practical Techniques for
Fast Data Manipulation. O’Reilly Media, Inc.
Nelson, J. (2016). Mastering Redis. Packt Publishing Ltd.
Redis. Documentation. https://redis.io/documentation.

55
© Editorial UOC Capítulo III. Estructuras de datos en Redis

Capítulo III
Estructuras de datos en Redis

1. Introducción

En este capítulo se van a describir las principales estructuras


de datos de Redis y algunas de las operaciones asociadas a estas.
En este sentido, HELP es un comando fundamental dado que,
aplicado a otro comando, permite recuperar información acerca
del funcionamiento de este último: parámetros, ejemplos o for-
mas de usarlo. En la figura 1 se muestra un ejemplo de invoca-
ción del HELP sobre el comando SET.

Figura 1. Uso del comando HELP

Fuente: elaboración propia

2. Cadenas

Una cadena es un valor que puede ser de tipo textual (XML,


JSON, HTML o texto), valores enteros, reales o datos binarios
(vídeo, imágenes o audio), pero en cualquier caso no puede exce-
der los 512 Mb. El comportamiento de una cadena depende del

57
© Editorial UOC Introducción a las bases de datos NoSQ
L

tipo de valor que representa. Además para cada tipo de cadena


existen comandos específicos y que puede que no tengan sentido
para otros tipos de cadenas. A continuación se van a introducir
los más importantes.
Los comandos SET y GET sirven respectivamente para crear
una clave asociada a una cadena y recuperar la cadena asociada
a una clave. De forma similar, el comando MSET permite crear
varias claves a la vez especificando los pares clave-valor separa-
dos por espacios tal como se puede observar en la figura 2.

Figura 2. Uso del comando MSET

Fuente: elaboración propia

Por su parte, el comando MGET permite recuperar varios


valores a la vez indicando las claves separadas por espacios tal
como se muestra en la figura 3.

Figura 3. Uso del comando MGET

Fuente: elaboración propia

Existen un conjunto de comandos diseñados para gestio-


nar exclusivamente contadores. Se trata de INCR, INCRBY,
INCRFLOATBY, DECR o DECRBY que tienen como función
incrementar o disminuir el valor numérico asociado a una clave.
Relacionado con el comando INCR están los comandos INCRBY
y INCRBYFLOAT. Estos comandos, respectivamente, incremen-
tan el valor asociado a una clave por un número entero o un núme-
ro real especificado (no tiene por qué ser 1). Al igual que INCR,

58
© Editorial UOC Capítulo III. Estructuras de datos en Redis

retornan como resultado el valor final incrementado. Por último,


los comandos DECR y DECRBY disminuyen el valor asociado
a una clave por el número entero o real especificado y retornan
como resultado el valor disminuido. En todos los casos, se pueden
usar como valores de incremento/disminución números números
positivos o negativos. En la figura 4 se muestran algunos ejemplos
respecto a una clave a la que se asocia el valor 150.

Figura 4. Uso de los comandos de incremento y disminución

Fuente: elaboración propia

Observar que los comandos son atómicos. Es por esta razón


que el incremento/disminución se realiza en una única opera-
ción y no se puede dar el caso de que dos clientes diferentes que
estén ejecutando el mismo comando al mismo tiempo vayan a
obtener el mismo resultado.
Otro conjunto de comandos sirve para gestionar bits. Se trata
de los comandos SETBIT, GETBIT, BITCOUNT y BITOP. El
comando SETBIT establece a 0 o 1 una posición de un conjunto
de bits (y en caso de no existir la posición se crea). Por otra parte
el comando GETBIT permite recuperar el valor de una posición
de un conjunto de bits asociado a una clave. En la figura 5 se
muestra un ejemplo donde se han establecido a 1 los bits de las
posiciones 10 y 15, y después se recuperan.

59
© Editorial UOC Introducción a las bases de datos NoSQ
L

Figura 5. Uso de los comandos SETBIT y GETBI

Fuente: elaboración propia

EL comando BITCOUNT está asociado a los dos anteriores,


retorna el número de bits marcados a 1 de un conjunto de bits.
En la figura 6 se muestra la invocación del comando sobre el
ejemplo anterior.

Figura 6. Uso de BITCOUNT

Fuente: elaboración propia

En la tabla 1 se muestran los principales comandos relaciona-


dos con las cadenas y su significado.

60
© Editorial UOC Capítulo III. Estructuras de datos en Redis

Tabla 1. Comandos asociados a las cadenas

Comando Significado

APPEND Añade un valor al final del valor existente asociado a la clave (o


crea uno si no existe ninguno todavía).

BITCOUNT Cuenta el número de conjuntos de bits de una cadena. Puede


indicarse un intervalo de la cadena, especificando el comienzo y
final de esta.

BITOP Realiza una operación bit a bit entre varias claves (que contienen
valores de cadena) y almacena el resultado en la clave de destino.

BITPOS Devuelve la posición del primer bit con valor a 1 o 0 en una


cadena dada.

DECR Disminuye el valor asociado a la clave en 1.

DECRBY Disminuye el valor asociado a la clave por el número dado.

GET Recupera un único valor.

GETBIT Devuelve el valor del bit en la posición indicada en el valor de


cadena almacenado en key.

GETRANGE Retorna la subcadena del valor asociado a la clave indicando el


intervalo de comienzo y final. Estos valores pueden ser negativos si
se comienza por el final de la cadena (-1 indica el final).

GETSET Crea una clave simple y devuelve el valor antiguo asociado


a la clave. Se produce un error si no tenía valor asociado
anteriormente.

INCR Incrementa el valor asociado a la clave en 1.

INCRBY Incrementa el valor asociado a la clave por el número dado.

INCRBYFLOAT Incrementa el valor asociado a la clave por el número real dado.

MGET Recupera múltiples valores.

MSET Crea una clave múltiple.

MSETNX Crea una clave múltiple si no existe.

PSETEX Crea una clave con tiempo de expiración en milisegundos.

SET Crea una clave simple.

SETBIT Establece el valor de un bit en 0 o 1 en la posición indicada en el


valor de cadena almacenada para una clave dada.

SETEX Crear clave con tiempo de expiración en segundos.

61
© Editorial UOC Introducción a las bases de datos NoSQ
L

Comando Significado

SETNX Crea una clave si no existe.

SETRANGE Sobreescribe parte de la cadena almacenada en la clave,


comenzando en el desplazamiento especificado con la longitud del
valor. Si el desplazamiento es mayor que la longitud actual de la
cadena en la clave, la cadena se rellena con cero-bytes para hacer
ajuste de compensación.

STRLEN Longitud del valor asociado a la clave.


Fuente: elaboración propia

Por último, el comando BITOP permite realizar operacio-


nes entre los claves que tienen asociados conjuntos de bits.
El comando requiere que se especifique una operación entre
conjuntos de bits, una clave de destino, y una lista de claves que
tengan asociado un conjunto de bits. Las operaciones disponi-
bles son OR, AND, XOR y NOT. En la figura 7 se muestra un
ejemplo donde se realiza una operación de tipo OR sobre dos
claves que tienen asociadas conjuntos de bits.

Figura 7. Uso de BITOP

Fuente: elaboración propia

Algunos de los casos donde se pueden utilizar cadenas son


los siguientes:

• Implementación de mecanismos de caché para almacenar


texto o datos binarios tales como páginas html, respuestas de
API, vídeos o imágenes.

62
© Editorial UOC Capítulo III. Estructuras de datos en Redis

• Un sistema de caché con expiración automática. Para ello se


pueden usar cadenas que tengan asociadas claves con expira-
ción automática..
• Implementación de contadores.

3. Listas

Las listas representan un conjunto de valores ordenados para


las cuales se han definido operaciones tales como añadir valores
a la lista, recuperar el primer y último valor, o manipular los
valores usando los índices que indican su posición. Como están
implementadas en forma de listas enlazadas entonces permiten
la inserción de valores por la cabeza o la cola de la lista. Por otra
parte existen un tipo de operaciones denominadas bloqueantes,
dado que cuando se ejecutan sobre una lista vacía, tienen como
efecto que el sistema se quede esperando hasta que se añada un
nuevo elemento. Por otra parte, observaremos que las operacio-
nes sobre listas son atómicas.
A continuación se van a describir algunos de los comandos más
utilizados. En primer lugar, se encuentran los de inserción de datos
LPUSH y RPUSH, que sirven respectivamente para insertar datos al
principio y al final de una lista. En la figura 8 se muestra un ejemplo.

Figura 8. Uso de los comandos LPUSH y RPUSH

Fuente: elaboración propia

63
© Editorial UOC Introducción a las bases de datos NoSQ
L

En segundo lugar, se tienen los comandos LLEN y LINDEX.


Mediante el comando LLEN se puede obtener la longitud de
una lista y mediante el comando LINDEX se pueden recuperar
los valores de una lista especificando el índice que representa la
posición del valor en esta comenzado por el índice 0 para indi-
car la primera posición y el índice -1 para indicar la última. En
la figura 9 se muestra un ejemplo de cada uno de los comandos
descritos.

Figura 9. Uso de los comandos LLEN y LINDEX

Fuente: elaboración propia

En la tabla 2 se muestran los principales comandos relaciona-


dos con las listas y su significado.

Tabla 2. Comandos asociados a las listas


Comando Significado
BLPOP Es una versión bloqueante del comando LPOP. Se proporcionan
un conjunto de listas, de manera que se extrae un elemento de
la cabeza de la primera lista de las dadas que no esté vacía.
Las listas se comprueban en el orden especificado en el
comando. En caso de no existir elementos en ninguna de las
listas especificadas, entonces se bloquea al cliente que inició la
operación un tiempo especificado en el mismo comando.
BRPOP Es una versión bloqueante del comando RPOP. Se proporcionan
un conjunto de listas, de manera que se extrae un elemento
de la cola de la primera lista de las dadas que no esté vacía.
Las listas se comprueban en el orden especificado en el
comando. En caso de no existir elementos en ninguna de las
listas especificadas, entonces se bloquea al cliente que inició la
operación un tiempo especificado en el mismo comando.

64
© Editorial UOC Capítulo III. Estructuras de datos en Redis

Comando Significado
BRPOPLPUSH Es una versión bloqueante del comando RPOPLPUSH. La principal
diferencia con este último comando es que en caso de no existir
elementos para extraer de la lista especificada, entonces se
bloquea al cliente que inició la operación un tiempo especificado
en el mismo comando. Si existen elementos entonces se
comporta exactamente igual que RPOPLPUSH.
LINDEX Devuelve el valor situado en el índice dado de la lista
almacenada (se empieza a contabilizar por 0 al principio de la
lista y por -1 al final de la lista).
LINSERT BEFORE/ Inserta un valor en la lista almacenada antes o después del valor
AFTER pivote proporcionado.
LLEN Obtener la longitud de la lista almacenada.
LPOP Elimina y retorna el primer elemento de la lista almacenada.
LPUSH Inserta todos los valores especificados en la cabeza de la lista
almacenada. Si la clave no existe, se crea una lista vacía antes
de realizar la operación.
LPUSHX Igual que LPUSH, pero debe existir la clave y contener una lista,
en caso contrario no realiza ninguna operación.
LRANGE Devuelve los elementos especificados de la lista almacenada en
el intervalo de valores especificados. Los índices se especifican
empezando desde 0 para el principio de la lista o -1 para el final
de la lista.
LREM Elimina las n ocurrencias de un valor dado de la lista
almacenada, de manera que si n > 0 se eliminan empezando
desde la cabeza a la cola de la lista, si n > 0 se eliminan
empezando desde la cola a la cabeza y si n = 0 se eliminan
todos las ocurrencias de la lista.
LSET Introduce el valor dado en la posición establecida de la lista
almacenada.
LTRIM Recorta una lista para que contenga solo el rango de elementos
especificados por dos índices que indican el comienzo y final de
la sublista (los índices se comienzan a contar desde 0).
RPOP Elimina y retorna el último elemento de la lista almacenada.
RPOPLPUSH Devuelve y elimina atómicamente el último elemento de la lista
almacenada e introduce el elemento en la primera posición de
la otra lista especificada.
RPUSH Inserta todos los valores especificados en la cola de la lista
almacenada. Si la clave no existe, se crea una lista vacía antes
de realizar la operación.
RPUSHX Igual que RPUSH, pero debe existir la clave y contener una lista,
en caso contrario no realiza ninguna operación.
Fuente: elaboración propia

65
© Editorial UOC Introducción a las bases de datos NoSQ
L

Para recuperar los valores de una lista, también existen los


comandos LPOP y RPOP. Estos comandos permiten respecti-
vamente recuperar el primer y último elemento de una lista dada
pero eliminándolo de esta. En la figura 10 se muestra un ejemplo
de su uso sobre las listas del ejemplo anterior.

Figura 10. Uso de los comandos LPOP y RPOP

Fuente: elaboración propia

Por último, mencionaremos el comando LRANGE, que per-


mite recuperar una sublista de elementos a partir de una lista
dada. Para ello es necesario especificar un intervalo de índices de
comienzo y final de la sublista. Tal como se ha comentado antes,
el índice 0 indica la primera posición y el índice -1 indica la última
posición de la lista. En la figura 11 se muestra un ejemplo de uso.

Figura 11. Uso del comando LRANGE

Fuente: elaboración propia

Algunos ejemplos de uso en el que son útiles las listas son los
siguientes:

66
© Editorial UOC Capítulo III. Estructuras de datos en Redis

• Implementación de una colección, una pila o una cola.


• Implementación de una cola de eventos.
• Almacenamiento de los posts de usuarios más recientes.

4. Hash

Representa un conjunto de pares clave-valor donde cada clave


permite acceder a un valor asociado. Tanto la clave como el valor
son cadenas. Se implementa como una lista doblemente enlazada
diseñada para ser eficiente en memoria. De esta forma el acceso
a un hash está optimizado y se pueden realizar búsquedas rápi-
das. La principal ventaja de este tipo de datos es que es posible
acceder y actualizar valores concretos sin tener que recuperar o
modificar todo el conjunto de datos asociado a la clave.
A continuación se muestran los principales comandos asocia-
dos a un hash. En primer lugar, se encuentran los comandos HSET
y HMSET, que se usan para insertar datos. El comando HSET
permite asociar un valor a una clave mientras que el comando
HMSET permite hacer la misma operación sobre un conjunto
de pares clave-valor separados por espacios. En cualquiera de los
casos, si no existen los campos involucrados, se crean y, si existen,
se sobreescriben los valores que contengan. En la figura 12 se
muestra un ejemplo de uso de ambos comandos.

Figura 12. Uso de los comandos HSET y HMSET

Fuente: elaboración propia

67
© Editorial UOC Introducción a las bases de datos NoSQ
L

En segundo lugar, se encuentran los comandos HGET y


HMGET, que permiten respectivamente recuperar el valor aso-
ciado a una clave de un hash determinado y recuperar los valores
de un conjunto de claves especificadas separadas por espacios. En
la figura 13 se muestra un ejemplo de uso de ambos comandos.

Figura 13. Uso de los comandos HGET y HMGET

Fuente: elaboración propia

En la tabla 3 se resumen los principales comandos relaciona-


dos con los hashes y su significado.

Tabla 3. Comandos asociados a los hashes

Comando Significado

HDEL Elimina los campos especificados del hash almacenado en la clave.

HEXISTS Retorna 1 si el hash contiene el campo indicado o 0 si no lo


contiene o la clave no existe.

HGET Retorna el valor asociado con el campo del hash almacenado.

HGETALL Retorna todos los campos y valores del hash almacenado.

HINCRBY Incrementa el número asociado al campo del hash almacenado


por el incremento especificado. Si la clave no existe, se crea una
nueva clave para contener al hash. Si el campo no existe, el valor
se establece en 0 antes de que se realice la operación.

HINCRBYFLOAT Actúa igual que HINCRBY pero con incrementos reales.

HKEYS Retorna todos los nombres de los campos del hash almacenado.

HLEN Retorna el número de campos que hay en el hash almacenado.

HMGET Retorna los valores asociados a los campos especificados en el


hash almacenado en la clave. Para cada campo no existente, se
devuelve un valor nulo.

68
© Editorial UOC Capítulo III. Estructuras de datos en Redis

Comando Significado

HMSET Asocia a los campos especificados, los valores indicados en el


hash almacenado en la clave. Sobreescribe cualquier campo
especificado ya existente en el hash. Si la clave no existe, se crea
una nueva clave para contener al hash.

HSET Asocia al campo especificado el valor indicado y lo guarda en el


hash almacenado. Si la clave no existe, se crea, y si el campo ya
existe, se sobreescribe.

HSETNX Asocia al campo especificado el valor indicado y lo guarda en el


hash almacenado solo en el caso de que el campo no exista.

HSTRLEN Devuelve la longitud del valor asociado al campo en el hash


almacenado en la clave. Si la clave o el campo no existen, se
devuelve 0.

HVALS Retorna todos los valores que hay en el hash almacenado en la


clave
Fuente: elaboración propia

En tercer lugar, se pueden destacar un conjunto de comandos


que ofrecen información sobre la estructura de un hash. Se trata
de HGETALL, HKEYS y HVALS. El comando HGETALL
permite recuperar todos los pares clave-valor almacenados en
un hash, HKEYS permite recuperar las claves utilizadas y, por
último, HVALS permite recuperar los diferentes valores almace-
nados. En la figura 14 se muestra un ejemplo de los comandos
mencionados.

Figura 14. Uso de los comandos HGETALL, HKEYS y HVALS

Fuente: elaboración propia

69
© Editorial UOC Introducción a las bases de datos NoSQ
L

Por último, quedan por mencionar los comandos HDEL, que


permiten eliminar un par clave-valor de un hash especificando
la clave del par, y HINCRBY, que permite incrementar el valor
numérico asociado a una clave. En la figura 15 se muestra un
ejemplo de los comandos mencionados.

Figura 15. Uso de los comandos HDEL y HINCRBY

Fuente: elaboración propia

5. Conjuntos

Representa una colección no ordenada de cadenas diferentes


(por lo que no es posible añadir elementos repetidos). Se imple-
menta como una tabla hash, de manera que las operaciones sobre
conjuntos están optimizadas. A continuación se muestran los
principales comandos asociados a un conjunto. En primer lugar,
para insertar datos en un conjunto se utiliza el comando SADD,
que permite añadir uno o más elementos al conjunto, ignorando
los repetidos, y devolviendo como resultado el número de ele-
mentos añadidos. La figura 16 se muestra un ejemplo de uso del
comando.

70
© Editorial UOC Capítulo III. Estructuras de datos en Redis

Figura 16. Adicción de elementos con SADD

Fuente: elaboración propia

En segundo lugar, existen un grupo de comandos que imple-


mentan operaciones entre conjuntos. Se trata de los comandos
SINTER, SDIFF y SUNION. SINTER implementa la operación
de intersección entre varios conjuntos, SDIFF la diferencia entre
un conjunto y el resto de conjuntos especificados, y SUNION
la unión de los conjuntos especificados sin incluir valores dupli-
cados. La figura 17 muestra un ejemplo de uso de los comandos
descritos.

Figura 17. Operaciones conjuntistas

Fuente: elaboración propia

En tercer lugar, se encuentra un grupo de comandos que


ofrecen información sobre el conjunto. Se trata de los comandos
SCARD y SMEMBERS. El primero permite recuperar la cardi-
nalidad de un conjunto dado, mientras que el segundo recupera
todos los elementos de un conjunto. La figura 18 muestra un
ejemplo de uso de estos comandos.

71
© Editorial UOC Introducción a las bases de datos NoSQ
L

Figura 18. Operaciones de consulta

Fuente: elaboración propia

Por último, se encuentran los comandos SRANDMEMBER,


que permiten recuperar n elementos aleatorios de un conjunto;
SISMEMBER, que permite comprobar si un elemento concre-
to pertenece a un conjunto, y SREM que permite eliminar un
elemento de un conjunto. En la figura 30 se muestran varios
ejemplos de uso.

Figura 19. Otras operaciones sobre conjuntos

Fuente: elaboración propia

En la tabla 4 se muestran los principales comandos relaciona-


dos con los conjuntos y su significado.

72
© Editorial UOC Capítulo III. Estructuras de datos en Redis

Tabla 4. Comandos asociados a los conjuntos

Comando Significado

SADD Agrega los miembros especificados al conjunto almacenado


en la clave. Los miembros repetidos se ignoran, y si la clave no
existe, se crea un nuevo conjunto antes de realizar la agregación.

SCARD Retorna el número de elementos del conjunto.

SDIFF Devuelve los miembros del conjunto resultantes de la diferencia


entre el primer conjunto y todos los conjuntos sucesivos.

SDIFFSTORE Funciona igual que SDIFF, pero en lugar de devolver el conjunto


resultante, se almacena en el conjunto destino especificado (si
existe, se sobreescribe).

SINTER Devuelve los miembros del conjunto resultantes de la


intersección de todos los conjuntos dados.

SINTERSTORE Funciona igual que SINTER, pero en lugar de devolver el


conjunto resultante, se almacena en el destino (si existe, se
sobreescribe).

SISMEMBER Devuelve 1 si elemento dado es un miembro del conjunto


almacenado en clave, y 0 en caso contrario.

SMEMBERS Devuelve todos los elementos del conjunto almacenado en la


clave.

SMOVE Mueve un elemento de un conjunto dado a otro conjunto. Es


una operación atómica. Si el elemento especificado no existe, no
se hace nada, y si existe en el conjunto destino, simplemente se
elimina del conjunto origen.

SPOP Elimina y devuelve n elementos al azar del conjunto almacenado


en la clave.

SRANDMEMBER Devuelve n elementos al azar del conjunto almacenado en la


clave. Si el número es positivo, los elementos serán distintos, y si
el número es negativo, los elementos pueden ser repetidos.

SREM Elimina los miembros especificados del conjunto almacenado en


la clave.

SUNION Devuelve los miembros del conjunto resultante de la unión de


todos los conjuntos dados.

SUNIONSTORE Funciona igual que SUNION, pero en lugar de devolver el


conjunto resultante, se almacena en el destino (si existe, se
sobreescribe).
Fuente: elaboración propia

73
© Editorial UOC Introducción a las bases de datos NoSQ
L

Algunos ejemplos de uso en el que son útiles los conjuntos


son los siguientes:

• Filtrado de datos.
• Agrupamiento de datos.
• Comprobar la pertenencia de alguien a algo.

6. Conjuntos ordenados

Representa un conjunto de elementos distintos donde cada ele-


mento tiene asociado un valor numérico positivo o negativo que
se usa para ordenar los elementos del conjunto de menor a mayor
valor. En caso de existir elementos diferentes con el mismo valor
asociado, estos se ordenan lexicográficamente. Se implementan uti-
lizando dos estructuras de datos, por un lado una lista por saltos con
una tabla hash que permite buscar de manera eficiente dentro de una
secuencia ordenada de elementos y una lista doblemente enlazada
diseñada para ser eficiente en memoria. De esta forma las opera-
ciones son rápidas pero no tanto como en el caso de los conjuntos.
A continuación se van a presentar algunos de los comandos
más importantes. En primer lugar, el comando ZADD, que per-
mite añadir un conjunto de pares elementos-valor a un conjunto
ordenado y que devuelve como resultado el número de elemen-
tos que han sido añadidos. En la figura 20 se muestra un ejemplo
de uso del comando.

Figura 20. Adicción de elementos a un conjunto ordenado

Fuente: elaboración propia

74
© Editorial UOC Capítulo III. Estructuras de datos en Redis

En segundo lugar, existen una serie de comandos que


permiten recuperar elementos de un conjunto ordenado.
Se trata de los comandos ZRANGE, ZRANGEBYLEX,
ZRANGEBYSCORE, ZREVRANGE, ZREVRANGEBYLEX,
y ZREVRANGEBYSCORE. El comando ZRANGE, dado un
intervalo de posiciones, devuelve los elementos del conjunto
cuyas posiciones se encuentran dentro del intervalo dado consi-
derando que los elementos se encuentran ordenados de menor a
mayor. Los valores del intervalo empiezan en cero, y pueden ser
números negativos, en cuyo caso representan desplazamientos
desde el final, siendo -1 el último elemento. Este comando se
puede invocar con la opción WITHSCORES, en este otro caso
devolverá como resultado los elementos del conjunto selecciona-
do junto a los valores que tienen asociados. De forma similar, se
tiene el comando ZREVRANGE, que actúa igual que ZRANGE
pero en orden inverso, dado que los elementos se consideran
ordenados de mayor a menor. El resto de comandos tienen un
funcionamiento similar. En la figura 21 se muestra un ejemplo de
uso de los comandos descritos.

Figura 21. Uso de ZRANGE Y ZREVRANGE

Fuente: elaboración propia

75
© Editorial UOC Introducción a las bases de datos NoSQ
L

También es posible utilizar los valores asociados a los ele-


mentos en el proceso de recuperación. Así, se tienen el comando
ZSCORE, que retorna el valor de un elemento dado, ZRANK
que retorna la posición de un elemento dentro del conjunto
ordenado considerando que los elementos se encuentran orde-
nados de menor a mayor empezando desde 0 y, por último,
ZREVRANK que retorna la posición de un elemento dentro del
conjunto ordenado considerando que los elementos se encuen-
tran ordenados de mayor a menor empezando desde 0. En la
figura 22 se muestra un ejemplo.

Figura 22. Uso de ZSCORE, ZRANK y ZREVRANK

Fuente: elaboración propia

Por último, se puede eliminar un elemento de un conjunto


ordenado usando el comando ZREM. En la figura 23 se muestra
un ejemplo de uso de este comando.

76
© Editorial UOC Capítulo III. Estructuras de datos en Redis

Figura 23. Uso de ZREM

Fuente: elaboración propia

En la tabla 5 se muestran los principales comandos relaciona-


dos con los conjuntos ordenados y su significado.

Tabla 5. Comandos asociados a los conjuntos ordenados

Comando Significado

ZADD Agrega los pares miembro-puntuación especificados


al conjunto ordenado. Si un miembro ya existe, la
puntuación se actualiza y el elemento se vuelve a insertar
en la posición correcta para garantizar el orden correcto.

ZCARD Devuelve la cardinalidad del conjunto ordenado

ZCOUNT Devuelve el número de elementos del conjunto ordenado


con una puntuación entre min y max. Los argumentos
min y max tienen el mismo significado que el descrito
para ZRANGEBYSCORE.

ZINCRBY Incrementa en n la puntuación del miembro especificado


en el conjunto ordenado. Si el miembro no existe en
el conjunto ordenado, entonces se agrega el incremento
como su puntuación y si la clave no existe entonces se
crea un nuevo conjunto con el miembro especificado
como su único miembro. Acepta números reales y
negativos (para disminuir la puntuación).

ZINTERSTORE Calcula la intersección entre varios conjuntos especificados


y almacena el resultado en un conjunto destino
también especificado en el comando. En el comando, es
obligatorio indicar el número de conjuntos que se desea
intersecar antes de especificar los conjuntos y el resto
de argumentos opcionales que pueden aparecer en este
comando. La puntuación resultante de un elemento es
la suma de sus puntuaciones en los conjuntos ordenados
donde existen. Las opciones WEIGHT y AGGREGATE
funcionan como en la unión.

77
© Editorial UOC Introducción a las bases de datos NoSQ
L

Comando Significado

ZLEXCOUNT Devuelve el número de elementos del conjunto


ordenado con un valor entre min y max usando el orden
lexicográfico para elementos con la misma puntuación.
Los argumentos min y max tienen el mismo significado
que el descrito para ZRANGEBYLEX.

ZRANGE Devuelve los elementos del conjunto ordenado


especificados en un intervalo cerrado. Los elementos
se consideran ordenados de menor a mayor. El orden
lexicográfico se utiliza para elementos con igual
puntuación. Tanto start como stop son índices basados
en cero, y pueden ser números negativos para indicar
desplazamientos desde el final, siendo -1 el último
elemento. Los índices fuera de rango no producirán
un error. Es posible pasar la opción WITHSCORES para
devolver las puntuaciones de los elementos junto con los
elementos.

ZRANGEBYLEX Devuelve todos los elementos del conjunto ordenado


con un valor entre min y max. El argumento LIMIT se
puede usar para obtener solo un rango de los elementos
coincidentes. Se usan los caracteres «(» y «[« para indicar
inclusión o no precediento a los elementos, y los símbolos
«+» y «-« para indicar límites infinitos.

ZRANGEBYSCORE Devuelve todos los elementos del conjunto ordenado con


una puntuación entre min y max (incluyendo elementos
con una puntuación igual a min o max). Los elementos se
consideran ordenados de menor a mayor.
Los elementos que tienen la misma puntuación se
devuelven en orden lexicográfico. El argumento LIMIT
opcional se puede usar para obtener solo un rango
de los elementos coincidentes. El argumento opcional
WITHSCORES hace que el comando devuelva el
elemento y su puntuación. Min y max pueden ser -inf y
+ inf, y se puede especificar un intervalo abierto con «(»
precediendo al elemento.

ZRANK Devuelve la posición de un miembro en el conjunto


ordenado, suponiendo las puntuaciones ordenadas de
menor a mayor (se comienza desde 0)

ZREM Elimina los miembros especificados del conjunto


ordenado si existen.

ZREMRANGEBYLEX Elimina todos los elementos del conjunto ordenado


con un valor entre min y max. Los argumentos min y
max tienen el mismo significado que el descrito para
ZRANGEBYLEX.

78
© Editorial UOC Capítulo III. Estructuras de datos en Redis

Comando Significado

ZREMRANGEBYRANK Elimina todos los elementos del conjunto ordenado


con rango entre el inicio y el fin. Tanto el inicio como
el fin son índices basados en 0 y pueden ser números
negativos que indican desplazamientos que empiezan en
el elemento con la puntuación más alta (-1 es el elemento
con la puntuación más alta) .

ZREMRANGEBYSCORE Elimina todos los elementos del conjunto ordenado con


una puntuación entre min y max (incluyendo elementos
con una puntuación igual a min o max). Los elementos se
consideran ordenados de menor a mayor.
Los elementos que tienen la misma puntuación se
devuelven en orden lexicográfico. Los argumentos min
y max tienen el mismo significado que el descrito para
ZRANGEBYSCORE.

ZREVRANGE Funciona igual que ZRANGE salvo que los elementos se


consideran ordenados de mayor a menor, y los elementos
de igual puntuación se consideran en orden lexicográfico
inverso.

ZREVRANGEBYSCORE Funciona igual que ZRANGEBYSCORE salvo que los


elementos se consideran ordenados de mayor a menor, y
los elementos de igual puntuación se consideran en orden
lexicográfico inverso.

ZREVRANK Devuelve la posición de un miembro en el conjunto


ordenado, suponiendo las puntuaciones ordenadas de
mayor a menor (se comienza desde 0).

ZSCORE Devuelve la puntuación del miembro en el conjunto


ordenado. Si el miembro no existe o la clave no existe, se
devuelve nil.

ZUNIONSTORE Calcula la intersección de los conjuntos y almacena


el resultado en el conjunto destino. Es obligatorio
proporcionar el número conjuntos a unir antes de pasar
los conjuntos y el resto de argumentos opcionales. La
puntuación resultante de un elemento es la suma de sus
puntuaciones en los conjuntos ordenados donde existen.
La opción WEIGHTS permite especificar un factor de
multiplicación para cada conjunto ordenado de entrada,
y la opción AGGREGATE permite especificar cómo se
agregan los resultados (suma, mínimo o máximo). Si el
destino ya existe, se sobreescribe.
Fuente: elaboración propia

79
© Editorial UOC Introducción a las bases de datos NoSQ
L

Algunos ejemplos de uso en el que son útiles los conjuntos


ordenados son los siguientes:

• Construir una lista de espera en tiempo real para un servicio


al cliente.
• Mostrar una tabla de clasificación de un juego en línea masivo
que muestra a los mejores jugadores, usuarios con puntuacio-
nes similares o las puntuaciones de amigos.
• Construir un sistema de autocompletar usando millones de
palabras.

7. HyperLogLog

No se trata de una estructura de datos, sino de un algorit-


mo que usa aleatorización para obtener una aproximación del
número de elementos únicos que existen en un conjunto. En
este sentido, tiene un error estándar del 0.81 %. El algoritmo es
aplicable a cualquier conjunto con independencia del número de
elementos que contenga.
Existe un conjunto de comandos asociados al mismo. En pri-
mer lugar, el comando PFADD, que permite añadir una o más
elementos a un HyperLogLog devolviendo como resultado el
valor 1 si la cardinalidad ha cambiado y el valor 0 en caso contra-
rio. En la figura 24 se muestra un ejemplo.

Figura 24. Uso de PFADD

Fuente: elaboración propia

80
© Editorial UOC Capítulo III. Estructuras de datos en Redis

En segundo lugar, el comando PFCOUNT puede recibir


como argumentos una clave o un conjunto de claves de tipo
HyperLogLog. Si recibe una única clave, entonces retorna la
cardinalidad aproximada del conjunto representado por la clave
y, si recibe un conjunto de claves, devuelve la cardinalidad apro-
ximada de la unión de todos los elementos únicos de los conjun-
tos representados por esas claves. En la figura 25 se muestra un
ejemplo de uso del comando.

Figura 25. Uso de PFADD

Fuente: elaboración propia

Por último, encontramos el comando PFMERGE, que dada


una clave destino y una o más claves de tipo HyperLogLog,
devuelve como resultado un conjunto en el que se encuentran
mezclados los elementos de ambos HyperLogLogs y le asocia el
resultado a la clave destino especificada. En la figura 26 se mues-
tra un ejemplo de su uso.

Figura 26. Uso de PFMERGE.

Fuente: elaboración propia

Algunos ejemplos de uso en el que son útiles del tipo


HyperLogLog son los siguientes:

81
© Editorial UOC Introducción a las bases de datos NoSQ
L

• Contar el número de usuarios únicos que visitan un sitio web.


• Contar el número de términos distintos que fueron buscados
en un sitio web, en un momento preciso.
• Contar el número de hashtags distintos que fueron utilizados
por un usuario.
• Contar el número de palabras distintas que aparecen en un
libro.

82
© Editorial UOC Capítulo III. Estructuras de datos en Redis

Bibliografía
Carlson, J. L. (2013). Redis in action. Manning Publications Co.
Da Silva, M. D.; Tavares, H. L. (2015). Redis Essentials. Packt Publishing
Ltd.
Das, V. (2015). Learning Redis. Packt Publishing Ltd.
Macedo, T., & Oliveira, F. (2011). Redis Cookbook: Practical Techniques for
Fast Data Manipulation. O’Reilly Media, Inc.
Nelson, J. (2016). Mastering Redis. Packt Publishing Ltd.
Redis. Ddocumentation. https://redis.io/documentation.

83
© Editorial UOC Capítulo IV. Persistencia, replicación y particionamiento

Capítulo IV
Persistencia, replicación y particionamiento

1. Introducción

En este capítulo se van a tratar tres aspectos fundamentales en


la gestión de la base de datos Redis. Por una parte se comentarán
los mecanismos de aseguramiento de la persistencia que garanti-
zan la durabilidad de los datos. Y por otra parte, se trataran dos
de las características comunes a las bases de datos NoSQL: la
replicación y el particionamiento. La combinación de estas herra-
mientas asegura el acceso rápido y eficiente a los datos.

2. Persistencia

Redis almacena la información en memoria de manera que si


se produce un fallo en esta se pierden los datos. Para resolver este
problema, existen dos mecanismos de gestión de la persistencia:

2.1. Redis Database (RDB)

Un archivo .rdb es un formato binario que almacena una


instancia de Redis en un momento temporal determinado. Se
caracteriza por:

85
© Editorial UOC Introducción a las bases de datos NoSQL

• Su representación interna es similar a la representación en


memoria.
• Está optimizado para soportar lecturas y escrituras rápidas.
• Se puede programar la creación de estos archivos en diferen-
tes intervalos de tiempo ( horas, días, semanas o meses).
• Un único archivo .rdb permite restaurar una instancia de Redis
completa. En este sentido es útil para realizar backups y poder
restaurar cualquier conjunto de datos en cualquier momento.

Existen dos comandos para crear un archivo .rdb. El coman-


do SAVE lo crea de forma inmediata, pero bloquea el servidor
durante la creación, y el comando BGSAVE hace la misma ope-
ración, pero se ejecuta en segundo plano en un proceso secunda-
rio de manera que el servidor no queda bloqueado. En este caso
el proceso principal no realiza ninguna operación de E/S, y si se
reciben peticiones de escrituras, será el proceso hijo el encargado
de copiar los cambios producidos por estas.
La configuración de la periodicidad de la creación de los
archivos se realiza en el archivo de configuración de Redis (redis.
conf que se puede encontrar en el directorio del código fuente)
mediante la inserción de reglas del tipo:

save número_segundos número_cambios

La regla significa que si en X segundos se han producido Y ope-


raciones de escritura entonces, se creará un archivo de tipo .rdb.
Algunas características:

• Este sistema de reglas proporciona flexibilidad en cuanto a la


frecuencia en la que se crean los archivos, sin embargo no es

86
© Editorial UOC Capítulo IV. Persistencia, replicación y particionamiento

recomendable que las directivas estén separadas unas de otras


por menos de 30 segundos.
• Se puede deshabilitar este sistema eliminando las reglas del
archivo redis.conf y reiniciando el servidor.
• Este sistema no garantiza la recuperación de todos los datos
con ninguna combinación de frecuencia-cambios.
• Cuando se crea el proceso hijo encargado del archivo .rdb,
puede ocurrir que el proceso principal deje de estar disponible
para los clientes de la base de datos durante un intervalo de
tiempo que dependerá del hardware y el tamaño de los datos
que deben procesarse.

Existen un conjunto de directivas que permiten configurar los


archivos .rdb tal como se muestran en la tabla 1.

Tabla 1. Directivas de configuración de los archivos .rdb

Directiva Significado

stop-writes-on- Puede tomar el valor yes o no. Si toma el valor yes indica que
bgsave-error el sistema debe parar de aceptar escrituras si el último proceso
de creación falló. El sistema acepta escrituras si el proceso de
creación termina con éxito.

rdbcompression Indica si se debe comprimir o no el archivo rdb. Puede tomar


el valor yes o no.

rdbchecksum Puede tomar el valor yes o no Si toma el valor yes, se


almacena una marca al final del archivo .rdb de manera que
cuando se va a cargar el archivo se genera la misma marca y
se comprueba si son iguales. En caso de ser iguales se permite
la carga.

GEÀOHQDPH Establece el nombre del archivo .rdb.

save Establece la frecuencia de creación del archivo .rdb en función


del número de segundos y cambios que se producen. Por
defecto toma los valores save 3600 1, save 300 100, y
save 60 10000.
dir Especifica el directorio donde se encuentran localizados los
archivos AOF y RDB.
Fuente: elaboración propia

87
© Editorial UOC Introducción a las bases de datos NoSQL

2.2. Append-only file (AOF)

Se trata de una alternativa al sistema de archivos .rdb. El fun-


cionamiento de AOF consiste en que cada vez que se ejecuta
un comando sobre la base de datos, este es almacenado en un
archivo no binario denominado AOF (append-only file), de manera
que si es necesario realizar una restauración de datos, lo que se
hace es ejecutar todos los comandos almacenados en el archivo
en el mismo orden para reconstruir el estado original de la base
de datos.
Algunas características:

• En caso de corrupción del archivo, este puede ser recuperado


mediante una herramienta de reparación denominada redis-
check-aof.
• Al ser un archivo no binario, su contenido puede ser editado
y leído.
• Este sistema afecta al rendimiento y al espacio en disco.
• Se puede optimizar el archivo en una versión más pequeña
usando el comando BGREWRITEAOF. En caso de pro-
blemas en la optimización, el archivo original se mantiene
intacto.

Existen un conjunto de directivas que permiten configurar los


archivos AOF tal como se muestra en la tabla 2.

88
© Editorial UOC Capítulo IV. Persistencia, replicación y particionamiento

Tabla 2. Directivas de configuración de los archivos AOF

Directiva Significado

appendonly Toma el valor yes o no. Sirve para habilitar


o deshabilitar el archivo AOF. Por defecto está
deshabilitado.

DSSHQGÀOHQDPH Especifica el nombre del archivo AOF. Está vacío por


defecto.

appendfsync Existe un proceso que se ejecuta en segundo plano


denominado fsync( ) que realiza una llamada al
sistema operativo para que envíe los datos al disco. Se
puede configurar en base a tres valores:
no: no se ejecuta el proceso y es el sistema operativo
el que decide cuando descargar los datos. Es la opción
más rápida.
always: se ejecuta el proceso en cada escritura. Es la
opción más costosa pero más segura.
everysec: se ejecuta el proceso cada segundo.
Proporciona un buen rendimiento y es la opción por
defecto.

no-appendfsync-on- Toma el valor yes o no. Si la política appendfsync


rewrite está configurada a everysec o always y se está
ejecutando el proceso fsync( ) en segundo plano o
realizando una reescritura del archivo AOF, entonces
se puede bloquear el sistema de entrada/salida. Solo
se debería usar cuando existan problemas de latencia.
Por defecto toma el valor no.

auto-aof-rewrite- Toma un valor entre 0 y 100. Permite reescribir


percentage el archivo mediante el comando BGREWRITEAOF
si el tamaño del archivo crece en un porcentaje
especificado. Por defecto toma el valor 100.

auto-aof-rewrite-min- Tamaño mínimo de AOF para ser reescrito. Esta


size directiva tiene prioridad sobre lo especificado en
auto-aof-rewrite-percentage. El valor por defecto
es de 67108864 bytes.

aof-load-truncated Toma el valor yes o no. Si se produce un fallo el


archivo AOF puede ser truncado. Esta opción indica si
el sistema puede cargar el archivo cargar truncado y
emitir un error o no cargarlo y emitir un error.

dir Especifica el directorio donde se encuentra localizado


los archivos AOF y RDB.
Fuente: elaboración propia

89
© Editorial UOC Introducción a las bases de datos NoSQL

Algunas observaciones:

• La restauración de datos usando el sistema RDB es más rápida


que el sistema AOF debido a que no es necesario volver a eje-
cutar cada cambio realizado en la base de datos, simplemente
consiste en cargarlos.
• Pueden usarse ambas estrategias, de manera que si existen los
dos archivos, el sistema AOF tiene preferencia sobre RDB
dado que garantiza la durabilidad.
• Se pueden seguir las siguientes reglas para seleccionar una
estrategia u otra dependiendo las necesidades de persisten-
cia. Si no es necesaria la persistencia se pueden deshabilitar
ambos sistemas, si existe tolerancia a la pérdida de datos,
entonces se puede usar RDB y, por último, si se requiere
persistencia duradera, entonces se deberían usar ambos sis-
temas, RDB y AOF.

2.3. Replicación

Consiste en mantener copias de los datos en varias instancias


de la base de datos. Así se distingue una instancia denominada
«maestro», de manera que cada vez se escribe en ella, se realiza
una copia de la escritura en el resto de instancias que reciben
el nombre de «esclavos». Se hace una replicación asíncrona de
forma que cada cierto periodo de tiempo los esclavos reciben
datos para replicar. También es posible que entre las instancias
«esclavo» puedan existir conexiones.

90
© Editorial UOC Capítulo IV. Persistencia, replicación y particionamiento

Figura 1. Un nodo servidor y dos nodos clientes

Fuente: elaboración propia

91
© Editorial UOC Introducción a las bases de datos NoSQL

Se permite convertir una instancia en un esclavo de tres for-


mas diferentes:

• Usar el comando SLAVEOF IP PORT.


• Usar en la instancia de redis-server la opción –slaveof IP
PORT
• Añadir una directiva «slaveof IP PORT» al archivo de confi-
guración del servidor y usar esta configuración.

En la figura 1 se muestra un ejemplo de una instancia «maes-


tro» y dos instancias «esclavos». Para ello se abren tres terminales
distintas, de manera que en la primera terminal se escribe: redis-
server –port 5555, en la segunda se escribe: redis-server --port
6666 –slaveof 127.0.0.1 5555, y en la última: redis-server
--port 7777 –slaveof 127.0.0.1 5555). En la figura 2 se abre
otra terminal donde se añadirá una clave al servidor, y a continua-
ción se consulta a las instancias «esclavos» para comprobar que se
ha realizado la copia de lo escrito en el «maestro».

Figura 2. Prueba del funcionamiento de la replicación

Fuente: elaboración propia

El comando SLAVEOF NO ONE permite convertir un servi-


dor esclavo en un servidor maestro (es útil cuando falla un nodo

92
© Editorial UOC Capítulo IV. Persistencia, replicación y particionamiento

maestro). Se va a considerar el ejemplo anterior, y se va a hacer


caer la instancia que se ejecuta en el puerto 5555. A continuación,
se configura una de las instancias que actúa como esclavo como
nuevo maestro y los restantes esclavo se configuran para que repli-
quen al nuevo maestro. En la figura 3 se muestra el proceso.

Figura 3. Cambio de servidor maestro

Fuente: elaboración propia

Algunas de las principales aplicaciones de la replicación son:

• Permite mejorar la escalabilidad, dado que todas las operacio-


nes de lectura serán redirigidas hacia los nodos «esclavos» y las
escrituras se realizarán solo sobre el nodo «maestro».
• Permite la redundancia de datos, dado que es posible realizar
copias de los datos en las diferentes réplicas.
• Permite desactivar las operaciones de entrada/salida en el
nodo maestro realizando para ello la persistencia sobre las
réplicas. En este caso, el nodo maestro debería tener deshabi-
litada la persistencia y no reiniciarse pues, de lo contrario, al
reiniciarse vacío y replicarse, se borrarían todos los datos de
las réplicas.

93
© Editorial UOC Introducción a las bases de datos NoSQL

La consistencia de los datos se puede mejorar si se establece


como requisito que exista un número mínimo de réplicas conec-
tadas al maestro, de forma que una operación de escritura se
ejecuta solo si se satisface la condición del número de replicas
conectadas junto con una condición de latencia máxima de repli-
cación expresada en segundos (obsérvese que este esquema de
funcionamiento no garantiza que todas las replicas hayan acep-
tado las operaciones de escritura, solo que están conectadas). La
configuración se realiza usando los parámetros min-slaves-to-
write y min-slaves-max-lag que toman los valores por defecto
0 y 10 respectivamente.
Las réplicas son útiles siempre que el servidor maestro falla,
puesto que contienen los datos más recientes, y cualquiera
de ellas puede sustituir al servidor maestro. Sin embargo, cuan-
do el sistema funciona en modo simple, la conversión de un
nodo esclavo a nodo maestro no se realiza de forma automática,
de manera que habrá que configurarlo manualmente.

2.4. Particionamiento

Inicialmente Redis no fue diseñado para distribuir sus datos


entre diferentes instancias, sin embargo hay situaciones donde
un único servidor no es suficiente, como cuando la cantidad de
datos que hay que almacenar es superior a la memoria disponible
de Redis.
Redis admite el particionamiento de los datos, es decir, la divi-
sión de los datos en varias instancias, donde cada una solo con-
tendrá un subconjunto de las claves definidas. Sin embargo, exis-
ten dos tipos de particionamiento: horizontal y vertical. En este
contexto, el particionamiento horizontal significa la distribución

94
© Editorial UOC Capítulo IV. Persistencia, replicación y particionamiento

de claves en diferentes instancias de Redis mientras que el parti-


cionamiento vertical consiste en la distribución de los valores de
las claves en diferentes instancias de Redis. Así, por ejemplo, si se
tuvieran dos conjuntos de datos, en el particionamiento horizon-
tal cada conjunto de datos entero se almacenaría en una instancia
de Redis diferente, mientras que en un particionamiento vertical
los valores de cada conjunto se distribuirían entre diferentes
instancias.
Se van a considerar dos tipos de particionamientos:

a) Por división del rango. Los datos se distribuyen de acuer-


do a rangos de claves, y se asignan rangos de claves a instan-
cias específicas de la base de datos. Esta aproximación tiene
ciertas desventajas tales como:

• Las distribuciones probablemente serán desiguales, y habrá


rangos de claves mayores que otros.
• No permite cambiar fácilmente la lista de servidores
existentes, dado que si el número de instancias de Redis
cambia, entonces la distribución de rangos debe cambiar
también. En este sentido la agregación o eliminación de un
servidor, invalide parte de los datos.

b) Por hash. Se utiliza una función hash que permite conver-


tir las claves en un número y después almacenar los datos en
diferentes instancias. Para ello se aplica la función hash a la clave
de Redis, se divide el valor obtenido por el número de instan-
cias y se usa el resto de esa división como índice de acceso a
aquellas disponibles. La eficiencia de este método depende de
la eficiencia de la función hash que se haya elegido. Asimismo,
es preferible disponer de un número de instancias impar con

95
© Editorial UOC Introducción a las bases de datos NoSQL

el objetivo de minimizar colisiones. Por último, este método


de partición puede producir una falta de memoria caché si se
cambia el número de instancias.

La implementación del particionado puede ser responsabili-


dad de diferentes elementos:

• Particionamiento del lado del cliente. Es el cliente quien selec-


ciona el nodo donde debe escribir o leer una clave dada.
• Particionamiento asistido por proxy. El cliente envía una peti-
ción a un proxy, el cual actúa de intermediario para enviar la
petición al nodo correcto. Asimismo, se encarga de devolver
los resultados al cliente.
• Enrutado de consultas. Se envía la petición a una instancia
cualquiera, y esa instancia se encarga de reenviar la petición a
la instancia correcta.

El particionamiento tiene algunas desventajas tales como:

• Imposibilidad de realizar operaciones que requieran de múl-


tiples claves (intersección de dos conjuntos almacenados en
diferentes instancias).
• No se pueden realizar transacciones que involucren múlti-
ples claves. Asimismo, la implementación de estas se realiza
mediante programación directa del particionamiento.
• Cuando se usa particionamiento, la manipulación de datos es
más compleja.
• La granularidad de partición es la clave del particionamiento,
por lo que no es posible fragmentar un conjunto de datos
con una sola clave enorme como un conjunto ordenado muy
grande.

96
© Editorial UOC Capítulo IV. Persistencia, replicación y particionamiento

Redis se puede usar como almacén de datos o como caché,


pero tiene implicaciones importantes:

a) Si se utiliza como almacén de datos, una clave dada siem-


pre debe asignarse al mismo nodo de Redis. En este sentido, el
número de nodos debe ser fijo y no puede variar, y en caso con-
trario será necesario un sistema que pueda rebalancear las claves
entre los nodos cuando se agregan o eliminan los nodos.
b) Si se utiliza como caché,1 si un nodo determinado no
está disponible, entonces se usa un nodo diferente, alterando
el mapeo de instancias a claves. En este sentido, es fácil escalar
hacia arriba o hacia abajo.

Una forma de resolver el problema de escalar Redis cuando se


usa como almacén de datos consiste en crear desde el principio
un conjunto de instancias en un servidor inicial. Cuando crezcan
las necesidades de almacenamiento y se necesiten más servidores
de Redis, se moverán las instancias de un servidor a otro. Una vez
que se agregue el primer servidor adicional, se deberán mover la
mitad de las instancias de Redis del primer servidor al segundo, y
así sucesivamente. Si se usa la replicación, se puede hacer el cambio
con un tiempo de inactividad mínimo o nulo para sus usuarios:

• Se inician instancias vacías en el nuevo servidor.


• Se mueven los datos configurando estas nuevas instancias
como esclavos para sus instancias de origen.
• Se detienen los clientes.
• Se actualiza la configuración de las instancias movidas con la
nueva dirección IP del servidor.

1 https://redis.io/topics/lru-cache.

97
© Editorial UOC Introducción a las bases de datos NoSQL

• Se envía el comando SLAVEOF NO ONE a los esclavos en


el nuevo servidor.
• Se reinician los clientes con la nueva configuración actualizada.
• Finalmente se cierran las instancias que ya no se usan en el
servidor antiguo.

Por último, quedan por mencionar algunas implementaciones


del particionamiento en Redis:

• Redis Cluster.2 Ofrece particionamiento automático y de alta


disponibilidad. Es una mezcla entre el sistema de enrutado de
consultas y el particionamiento del lado del cliente.
• Twemproxy.3 Es un proxy desarrollado por Twitter que soporta
particionamiento entre múltiples instancias de Redis, con la
expulsión opcional del nodo si un nodo no está disponible
(esto cambiará el mapa de instancias de claves, por lo que debe
usar esta función solo si está usando Redis como caché). No es
un punto único de falla, ya que se pueden iniciar varios proxies
y configura los clientes para que se conecten al primero que
acepte la conexión. Por tanto, Twemproxy es una capa inter-
media entre clientes e instancias de Redis que maneja de forma
confiable la partición evitando las complejidades a los clientes.
• Clientes soportando hashing consistente. Se trata de usar
un cliente que implementa la partición del lado del cliente
mediante hashing consistente u otros algoritmos similares. Hay
varios clientes de redis con soporte para hashing consistente,
en particular Redis-rb4 y Predis.5

2 Se puede encontrar información sobre Redis Cluster en http://cort.as/-F2mp.


3 Se puede encontrar información sobre Twemproxy en http://cort.as/-F2mr.
4 Se puede encontrar información sobre redis-rb en http://cort.as/-F2mj.
5 Se puede encontrar información sobre Predis en http://cort.as/-F2mk.

98
© Editorial UOC Capítulo IV. Persistencia, replicación y particionamiento

Bibliografía
Carlson, J. L. (2013). Redis in action. Manning Publications Co.
Da Silva, M. D.; Tavares, H. L. (2015). Redis Essentials. Packt Publishing
Ltd.
Das, V. (2015). Learning Redis. Packt Publishing Ltd.
Nelson, J. (2016). Mastering Redis. Packt Publishing Ltd.
Redis. Documentation. https://redis.io/documentation

99
© Editorial UOC Capítulo V. Otros aspectos del uso de Redis

Capítulo V
Otros aspectos del uso de Redis

1. Introducción

En este capítulo se van a mostrar otras características de


las que dispone Redis tales como su sistema de mensajería, el
sistema transaccional, el lenguaje de script LuA y se describirá
brevemente cómo poder acceder a Redis desde el lenguaje de
programación Python.

2. El sistema publicador/suscrito

Redis implementa un sistema de mensajería donde los publi-


cadores envían mensajes a los suscriptores a través de un enlace
denominado canal. De esta forma, un publicador no sabe quié-
nes serán los receptores de sus mensajes, y de igual forma, un
suscriptor no sabrá quiénes son los publicadores de los que ha
recibido un mensaje. Asimismo, un cliente puede susbribirse a
cualquier número de canales.
En la figura 1 se tiene un ejemplo de publicador-suscriptor.
El suscriptor se ha enlazado a un canal denominado «ejemplo»
y existe un publicador que ha publicado en el canal el mensaje
«Esto es un ejemplo».

101
© Editorial UOC Introducción a las bases de datos NoSQL

Figura 1. Ejemplo de publicador y suscriptor

Fuente: elaboración propia

102
© Editorial UOC Capítulo V. Otros aspectos del uso de Redis

Un cliente se puede suscribir y darse de baja de cualquier


canal. Las respuestas a las operaciones de suscripción y cancela-
ción se envían en forma de una secuencia coherente de mensajes
donde el primer elemento indica el tipo de mensaje.
Un mensaje es una respuesta formada por tres elementos,
donde el primero de ellos puede ser:

• Subscribe. Significa que se ha realizado una suscripción con


éxito al canal especificado como el segundo elemento en la
respuesta. El tercer argumento representa el número de cana-
les suscritos actualmente.
• Unsubscribe. Significa que anulamos la suscripción al canal
especificado como segundo elemento en la respuesta. El ter-
cer argumento representa el número de canales a los suscritos
actualmente. Cuando el último argumento es cero, entonces
ya no se está suscrito a ningún canal, y el cliente puede emi-
tir cualquier tipo de comando Redis al estar fuera del estado
pub/sub.
• Message. Es un mensaje recibido como resultado de un
comando PUBLISH emitido por otro cliente. El segundo ele-
mento es el nombre del canal de origen, y el tercer argumento
es la carga útil del mensaje real.

El sistema soporta reconocimiento de patrones, de manera que


un cliente puede suscribirse a nombres de canales que coincidan
con un patrón determinado usando el comando PSUBSCRIBE.
En el siguiente ejemplo se realiza una suscripción a canales de
la forma noticias.arte, noticias.politica…:

PSUBSCRIBE noticias.*

103
© Editorial UOC Introducción a las bases de datos NoSQL

De igual forma se puede dar de baja una suscripción de


un conjunto de canales usando un patrón usando el comando
PUNSUBSCRIBE como en el ejemplo siguiente:

PUNSUBSCRIBE noticias.*

Los mensajes recibidos como resultado de la coincidencia de


patrones se envían en un formato de mensaje de tipo pmessage.
Se trata de un mensaje recibido como resultado de un comando
PUBLISH emitido por otro cliente, que coincide con una sus-
cripción de coincidencia de patrón. El segundo elemento es el
patrón original coincidente, el tercero, el nombre del canal de
origen y el último, la carga útil del mensaje real.
Por otro lado, el sistema confirma los comandos PSUBSCRIBE
y PUNSUBSCRIBE que envían un mensaje de tipo psubscribe y
punsubscribe utilizando el mismo formato que el formato de
mensaje de suscripción y cancelación de suscripción.
Por último observemos que:

1) Un cliente puede recibir un mismo mensaje varias veces si


está suscrito a múltiples patrones o varios patrones y canales que
coinciden con un mensaje publicado. En el siguiente ejemplo, el
cliente recibirá dos mensajes, uno de tipo message y otro de tipo
pmessage.

SUBSCRIBE canal
PSUBSCRIBE c.*

2) En los tipos de mensajes el último argumento es el núme-


ro de suscripciones activas. En este sentido, el cliente saldrá del
sistema de mensajería solo cuando este valor valga 0, es decir

104
© Editorial UOC Capítulo V. Otros aspectos del uso de Redis

cuando se haya cancelado la suscripción de todos los canales y


patrones.
A continuación, en la tabla 1, se muestran los comandos más
importantes relacionados con el sistema de mensajería.

Tabla 1. Comandos asociados al sistema de mensajería

Comando Significado

PSUBSCRIBE patrón Se suscribe a los canales que coinciden con los


patrones dados.

PUBSUB comando argumento Indica el estado del sistema de mensajería.

PUBLISH canal mensaje Publica un mensaje en el canal especificado.

PUNSUBSCRIBE patrón Deja de escuchar los mensajes publicados en los


canales que coinciden con los patrones dados.

SUBSCRIBE canal Escucha los mensajes publicados en los canales


dados.

UNSUBSCRIBE canal Deja de escuchar los mensajes publicados en los


canales dados.
Fuente: elaboración propia

3. Transacciones

En Redis se pueden definir transacciones que permiten eje-


cutar un grupo de comandos en un solo paso, es decir todos los
comandos se ejecutan secuencialmente como una sola opera-
ción aislada (no es posible interrumpir la ejecución de una tran-
sacción) de forma atómica (se procesan todos los comandos o
ninguno). El comando EXEC activa la ejecución de todos los
comandos de una transacción, por lo que si un cliente pierde
la conexión con el servidor en el contexto de una transacción
antes de llamar al comando MULTI, no se realiza ninguna de

105
© Editorial UOC Introducción a las bases de datos NoSQL

las operaciones. En caso contrario, se llama al comando EXEC


y se realizan todas.
Las transacciones se inician con el comando MULTI, a con-
tinuación se pasa una lista de comandos que se quieren ejecutar
dentro de la transacción, y por último, se ejecuta el comando
EXEC que inicia la transacción. Hasta que no se ejecuta EXEC,
los comandos emitidos se encolan. También es posible llamar al
comando DISCARD, que vaciará la cola de mensajes y saldrá de
la transacción.
En la figura 2 se tiene un ejemplo de transacción. Se comienza
con el comando MULTI, y después se añaden las sentencias SET
y GET. A continuación se ejecuta la transacción con el comando
EXEC.

Figura 2. Ejemplo de publicador y suscriptor

Fuente: elaboración propia

Se observa que:

• Cuando se emite un comando dentro del contexto de una


solicitud MULTI, cada comando responde con la cadena
QUEUED, que indica el encolamiento del mismo.

106
© Editorial UOC Capítulo V. Otros aspectos del uso de Redis

• EXEC devuelve un array de réplicas donde cada elemento es


la réplica a un único comando de la transacción en el mismo
orden en que los comandos fueron emitidos.
• Durante una transacción es posible encontrar dos tipos de
errores de comando. En primer lugar, es posible que un
comando no pueda encolarse, por lo que puede haber un
error antes de llamar a EXEC, o bien puede que un comando
falle después de llamar a EXEC.
En el primer caso, el servidor detecta que ha habido un
error al encolar, y no ejecutará la transacción. En el segun-
do, el resto de comandos se ejecutarán incluso si falla algún
comando durante la transacción.

El sistema de transacciones dispone del comando WATCH,


que permite mantener el seguimiento de determinadas claves, de
manera que si se detectan cambios en alguna antes de la ejecu-
ción del comando EXEC, se aborta la transacción y se retorna
una respuesta null indicando que la transacción falló. Este meca-
nismo es muy útil para gestionar condiciones de carrera. En el
siguiente ejemplo se controla la variable ejemplo:

WATCH ejemplo
valor = GET ejemplo
valor = valor + 1
MULTI
SET ejemplo $valor
EXEC

En este caso, si se produjera una condición de carrera y varios


clientes intentaran modificar a la vez el resultado de la variable

107
© Editorial UOC Introducción a las bases de datos NoSQL

avlor entre la llamada a T


C
A
WHyla llam
ada a EX
EC, la tran -
sacción fallaría.
Observeo ms que:

• Si la clave ivgilada exp


irara antes de ejecutar EX EC, se ejecu -
tarála transacción.
• Se upede llam ar a T
C
A
WHavrias evces. Sim
lem
p ente, todas
las llam adas de T C
A
WHtendrán el efecto de observar
los cam bios que com ienzan a partir de la llamada, hasta el
om
m ento en uqe se llam a a EX EC. aTm
bién p
uede enviar
cualquier núm ero de claves a una sola llam ada de T C
A
WH.
Cuando se llam a a EXEC, todas las claves dejan de ser o mni -
torizadas,indep endientem ente de si la transacción se abortó o
no. A
demás, cuando se cierra una conexión de cliente, se deja
de omnitorizar todo.
• Es o psible usar el com ando UNW C
T
AH(sin arguemntos)
ara liberar todas las claves o
p mnitorizadas yp oder utilizar
libremente las transacciones.

Acontinuación, en la tabla 2,se umestran los com


andos m
ás
im
ortantes relacionados con las transacciones.
p

Tabla 2. Comandos asociados a las transacciones

Comando Significado

DISCARD Descarta todos los comandos emitidos después de MULTI.

EXEC Ejecuta todos los comandos después de MULTI.

MULTI Marca el inicio de un bloque de transacción.

UNWATCH Olvida todas las claves controladas.

WATCH clave Controla las claves dadas para determinar la ejecución del bloque
MULTI-EXEC.
Fuente: elaboración propia

108
© Editorial UOC Capítulo V. Otros aspectos del uso de Redis

4. Sistema de canalización o pippeling

El funcionamiento básico de la canalización consiste en que


un cliente puede enviar varias solicitudes al servidor sin esperar
las respuestas, y al final podrá leer las respuestas en un solo paso.
Cuando se envían comandos utilizando la canalización, el ser-
vidor debe encolar las respuestas utilizando la memoria. Es por
ello que si necesita enviar una gran cantidad de comandos con la
canalización, es mejor hacerlo en lotes con un número razonable
de ellos.
Observemos que:

• La canalización, además de reducir el costo de latencia debi-


do al tiempo de ida y vuelta, también mejora las operaciones
totales que puede realizar por segundo en un servidor deter-
minado. Esto se debe a que el procesamiento de un comando
es muy barato desde el punto de vista de acceder a las estruc-
turas de datos y ofrecer una respuesta, pero es costoso desde
el punto de vista de generar el socket de entrada-salida (implica
invocar las llamadas al sistema read( ) y write( )) y realizar un
cambio de contexto).
• Cuando se utiliza la canalización, muchos comandos se leen
con una sola llamada al sistema read( ), y las respuestas múl-
tiples se entregan con una sola llamada al sistema write( ). Es
por ello que el número de consultas totales realizadas por
segundo aumenta al inicio casi de forma lineal con canaliza-
ciones más largas y, al final, alcanza 10 veces la línea de base
obtenida sin utilizar la canalización.

109
© Editorial UOC Introducción a las bases de datos NoSQL

5. El lenguaje Lua de scripting

Lua es un lenguaje de script interpretado por Redis. Para


ejecutar los scrips existen dos programas en Redis: EVAL y
EVALSHA.

a) EVAL
En este programa, el primer argumento es un conjunto de
comandos que se ejecutarán en el contexto del servidor Redis,
el segundo es el número de argumentos, el tercero son los argu-
mentos que representan nombres de clave y, a continuación,
aparecen otros argumentos adicionales que no son nombres de
clave. Desde los comandos de Lua se puede acceder a los argu-
mentos utilizando la variable global KEYS de forma indexada
empezando desde 1, y al resto de argumentos que no son clave
mediante la variable global ARGV. Por ejemplo:

eval “return {KEYS[1],KEYS[2],ARGV[1],ARGV[2]}” 2


clave1 clave2 valor1 valor2
1) “clave1”
2) “clave2”
3) “valor1”
4) “valor2”

Se puede llamar a comandos de Redis desde un script Lua


usando las funciones redis.call ( ) y redis.pcall ( ). Por ejemplo:

> eval “return redis.call(‘set’,KEYS[1],’valor’)” 1 clave

Ambas funciones son muy parecidas. Así, cuando una llama-


da a un comando Redis genera un error, entonces redis.call ( )

110
© Editorial UOC Capítulo V. Otros aspectos del uso de Redis

forzará a EVAL a devolverlo, mientras que redis.pcall ( ) lo inter-


ceptará y devolverá una tabla que representa el mismo.
Existe una conversión automática entre tipos de datos en Lua
y de Redis. Para ello se siguen unas reglas de conversión de datos:

• (QWHUR5HGLVȼ Número Lua


• &RQMXQWRGHGDWRV5HGLVȼ&DGHQD/XD
• 0~OWLSOHVFRQMXQWRVGHGDWRV5HGLVȼ7DEOD/XD 3XHGHWHQHU
otros tipos de datos Redis anidados).
• (VWDGR 5HGLV ȼ 7DEOD /XD FRQ XQ FDPSR TXH FRQWLHQH HO
estado
• 5HGLVHUURUȼ7DEODFRQXQFDPSRTXHFRQWLHQHHOHUURU
• &RQMXQWRGHGDWRVYDFtR5HGLVȼ9DORUERROHDQR)DOVH/XD
• 9DORUERROHDQR7UXH/XDȺ(QWHUR5HGLVFRQYDORU

Hay dos reglas que se deben tener en cuenta:

• Lua tiene un solo tipo numérico, números Lua. No hay dis-


tinción entre enteros y flotadores. Por lo tanto, siempre se
convierte los números Lua en enteros eliminando la parte
decimal del número, si corresponde. Para devolver un número
real desde Lua, se debe devolver como una cadena.
• Es complicado tener valores nulos dentro de un array Lua,
pues el proceso de conversión de Redis se detiene si se
encuentra un valor nulo.

Considerar los siguientes ejemplos:

> eval “return 10” 0


(integer) 10

111
© Editorial UOC Introducción a las bases de datos NoSQL

> eval “return {1,2,{3,’El coche rojo’}}” 0


1) (integer) 1
2) (integer) 2
3) 1) (integer) 3
2) “El coche rojo”

> eval “return redis.call(‘get’,’clave’)” 0


“valor”

> eval “return {1,2,3.3333,’casa’,nil,’camión’}” 0


1) (integer) 1
2) (integer) 2
3) (integer) 3
4) “casa”

En el último ejemplo, la conversión se para al encontrarse un


«nil» y no se muestra el valor «camión».
Observemos que hay dos funciones especiales que se pueden
utilizar en los scripts de Lua:

• redis.error_reply (error_string) que devuelve una tabla con


el campo de error que contiene una cadena especificada en la
función.
• redis.status_reply (status_string) devuelve una tabla con un
campo que contiene la cadena especificada en la función.

Por último, queda mencionar que Redis garantiza la ejecución


atómica de los scripts, de manera que no se ejecutará ningún otro
script o comando Redis mientras se ejecuta otro.

112
© Editorial UOC Capítulo V. Otros aspectos del uso de Redis

b) EVALSHA
)XQFLRQD LJXDO TXH (9$/ SHUR HQ OXJDU GH WHQHU XQ script
como primer argumento, tiene el resumen SHA1 de un script, de
manera que:

• Si el servidor dispone de un script con un resumen SHA1 coin-


cidente, se ejecuta el script.
• Si el servidor no dispone de un script con ese resumen SHA1,
se devuelve un error que indica que se use EVAL.
Por ejemplo:

> set clave valor


OK
> eval “return redis.call(‘get’,’clave’)” 0
“valor”
> evalsha 8f8f8goll459l44fk7k9k44k578k765l4llfjj4 0
“valor”
> evalsha ejemplodenollamada 0
(error) `NOSCRIPT` No matching script. Please use
[EVAL](/commands/eval).

Se garantiza que los scripts ejecutados se encuentran en la


caché de una ejecución de una instancia de Redis para siempre.
En este sentido, si se realiza un EVAL contra una instancia de
Redis, todas las llamadas de EVALSHA subsiguientes tendrán
éxito. Para que se vacíe el cache de scripts eliminando todos los
ejecutados hasta el momento hay dos formas:

• (MHFXWDUHOFRPDQGR6&5,37)/86+
• Reiniciar una instancia de Redis.

113
© Editorial UOC Introducción a las bases de datos NoSQL

Redis dispone de un comando SCRIPT que se puede usar


para controlar el subsistema de scripting. Puede tomar los siguien-
tes valores:

• 6&5,37)/86+2EOLJDD5HGLVDYDFLDUHOFDFKpGHscripts.
• SCRIPT EXISTS sha1 sha2 … shaN. Dada una lista de resú-
menes de SHA1 como argumentos, este comando devuelve
una matriz de 1 o 0, donde 1 significa que SHA1 específico
se reconoce como un script ya presente en el caché de scripting,
mientras que 0 significa que no encontró un script con este
SHA1.
• SCRIPT LOAD script. Este comando registra el script especi-
ficado en el caché de script de Redis. El comando es útil para
asegurar que EVALSHA no fallará sin la necesidad de ejecutar
el script.
• SCRIPT KILL. Este comando interrumpe un script de larga
duración que alcanza el tiempo de ejecución máximo con-
figurado para los scripts. El comando SCRIPT KILL solo se
puede usar con scripts que no modificaron el conjunto de datos
durante su ejecución (ya que detener un script de solo lectura
no viola la atomicidad).

Se llama replicación de efectos de un script a la replicación de


los comandos de escritura únicos generados por este. En este
modo de replicación, mientras se ejecutan los scripts de Lua,
Redis recopila todos los comandos ejecutados y cuando finaliza
la ejecución del script, la secuencia de comandos que generó se
envuelve en una transacción MULTI / EXEC y se envía a las
UpSOLFDV\DODUFKLYR$2)
En relación con la replicación de efectos de script existe el
comando redis.set_repl ( ) que permite controlar el motor de

114
© Editorial UOC Capítulo V. Otros aspectos del uso de Redis

replicación de scripting. Este comando puede tomar cuatro argu-


mentos diferentes:
redis.set_repl(redis.REPL_ALL)²5HSOLFDHQ$2)\HOUHVWR
de replicas.
redis.set_repl(redis.REPL_AOF)²5HSOLFDWHVRORHQ$2)
redis.set_repl(redis.REPL_REPLICA) – Replicate solo en las
réplicas.
redis.set_repl(redis.REPL_SLAVE) – Se usa por compatibili-
dad con versiones anteriores.
redis.set_repl(redis.REPL_NONE) – No replica en ninguno.
De forma predeterminada, el motor de secuencias de coman-
dos siempre se establece en REPL_ALL. Por ejemplo:

redis.call (‘set’, ‘Clave1’, ‘Valor1’)


redis.set_repl (redis.REPL_NONE)
redis.call (‘set’, ‘Clave2’, ‘Valor2’)
redis.set_repl (redis.REPL_ALL)
redis.call (‘set’, ‘Clave3’, ‘Valor3’)

Después de ejecutar el script anterior, el resultado es que solo


VHFUHDUiQODVFODYHV$\&HQODVUpSOLFDV\$2)
Los scripts de Redis no pueden crear variables globales, de
manera que si una secuencia de comandos necesita mantener
el estado entre las llamadas se deben usar claves de Redis en
su lugar. Para evitar el uso de variables globales en los scripts se
puede declarar cada variable usando la palabra clave local. Si
se intenta el acceso a la variable global, el script finaliza y EVAL
devuelve un error (lo mismo ocurre ante el intento de acceder a
una variable global que no existe):

115
© Editorial UOC Introducción a las bases de datos NoSQL

redis > eval ‘ejemplo=10’ 0


(error) ERR Error running script (call to 8f8f8goll459l44f
k7k9k44k578k765l4llfjj4): user_script:1: Script attempted
to create global variable ‘ejemplo’

Otra posibilidad que ofrecen los scripts es la escritura en el


archivo de registro de Redis desde los scripts de Lua usando la
función redis.log (loglevel, mensaje) donde el mensaje es una
cadena y el loglevel representa los niveles de registro y puede
tomar los valores:

• redis.LOG_DEBUG
• redis.LOG_VERBOSE
• redis.LOG_NOTICE
• redis.LOG_WARNING

Se observa que solo se emitirán los registros producidos por


secuencias de comandos con un nivel de registro igual o superior
al nivel de registro de instancia de Redis configurado actualmente.
Por ejemplo la siguiente llamada:

redis.log (redis.LOG_WARNING, “Error en el script.”)

Generará lo siguiente:

[32343] 22 Mar 15:21:39 # Error en el script.

Los scripts están sujetos a un tiempo de ejecución máximo


(cinco segundos de forma predeterminada) que se puede modi-
ficar cambiando el parámetro lua-time-limit de configuración
que afecta el tiempo máximo de ejecución. Para ello se utiliza el

116
© Editorial UOC Capítulo V. Otros aspectos del uso de Redis

comando redis.confRXWLOL]DQGRHOFRPDQGR&21),**(7
&21),*6(7&XDQGRXQscript se ejecuta durante más tiempo
del especificado, ocurre lo siguiente:

• Se registra que un script se está ejecutando demasiado tiempo.


• Se comienza a aceptar comandos de otros clientes. Los únicos
comandos permitidos son SCRIPT KILL y SHUTDOWN
NOSAVE (para el resto de comandos se responderá con un
error OCUPADO). En este sentido, se ejecutará SCRIPT
KILL para finalizar una secuencia de comandos que ejecuta
solo comandos de solo lectura, y se utilizará SHUTDOWN
NOSAVE para finalizar una secuencia de comandos que eje-
cuta comandos de escritura.

Por último, observemos que cuando se ejecuta EVALSHA


en el contexto de una solicitud canalizada, se debe garantizar
el orden de ejecución de los comandos. En este sentido, si
EVALSHA devuelve un error NOSCRIPT, el comando no se
podrá volver a ejecutar nuevamente. Para evitar estos problemas,
se recomienda:

• Usar EVAL cuando se vaya a ejecutar una tubería.


• Acumular todos los comandos para enviar a la canalización,
comprobar los comandos EVAL y usar el comando SCRIPT
EXISTS para verificar si todos los scripts se encuentran defi-
nidos. En caso contrario se debe utilizar el comando SCRIPT
LOAD al principio de la tubería y usar EVALSHA para todas
las llamadas de EVAL.

117
© Editorial UOC Introducción a las bases de datos NoSQL

6. Operaciones de gestión

Existen varios comandos orientados a gestionar el servidor y


las conexiones de Redis:

6.1. Gestión de conexiones

Se tienen los comandos mostrados en la tabla 3:

Tabla 3. Comandos asociados a las transacciones

Comando Significado

ECHO mensaje Imprime la cadena dada.

PING Comprueba si el servidor está en ejecución.

QUIT Cierra la conexión actual.

SELECT índice Cambia de base de datos.

CLIENT LIST Devuelve la lista de clientes conectados al servidor.

CLIENT SETNAME Asigna un nombre a la actual conexión.

CLIENT GETNAME Permite suspender a los clientes durante un tiempo


especificado en milisegundos.

CLIENT PAUSE Es un comando de control de conexión.

CLIENT KILL Cierra una conexión de cliente dada.


Fuente: elaboración propia

6.2. Gestión de la seguridad

En la base de datos se puede añadir un nivel de seguridad de


forma que cualquier cliente tenga que autenticarse antes de eje-
cutar un comando. En este sentido, lo primero que hay que hacer
es configurar un password con el comando CONFIG set require-

18
© Editorial UOC Capítulo V. Otros aspectos del uso de Redis

pass password. Una vez configurado el password, cada vez que


se vaya a ejecutar un comando será necesario utilizar el comando
AUTH comando. En la figura 3 se muestra un ejemplo donde
se configura un password. A continuación, para ejecutar cualquier
comando hay que autenticarse con el comando AUTH.

Figura 3. Configuración de un password

Fuente: elaboración propia

Se puede conocer el password configurado usado el comando


CONFIG get requirepass.

6.3. Gestión del servidor

Se trata de un conjunto de comandos orientados a gestionar


el servidor. En la tabla 4 se muestran algunos de los principales.

119
© Editorial UOC Introducción a las bases de datos NoSQL

Tabla 4. Comandos para gestionar el servidor

Comando Significado

BGREWRITEAOF Indica que se inicie un proceso de reescritura de un


archivo de tipo append-only.

CLIENT KILL Elimina la conexión de un cliente.

CLIENT LIST Lista de clientes conectados a un servidor.

CLIENT GETNAME Obtiene el nombre de la conexión actual.

CLIENT PAUSE timeout Detiene el procesamiento de comandos de los clientes


por un tiempo específico.

CLIENT SETNAME Establece el nombre de la conexión actual.

CLUSTER SLOTS Consigue un mapeo de nodos en el clúster.

COMMAND COUNT Número total de comandos.

COMMAND GETKEYS Obtiene las claves de un comando dado.

COMMAND INFO Obtiene detalles específicos de un comando.


nombre_comando

CONFIG GET parametro Obtiene el valor de un parámetro de configuración.

CONFIG REWRITE Reescribe del archivo de configuración con la


configuración en memoria.

CONFIG SET parámetro Establece un parámetro de configuración al valor dado.


valor

CONFIG RESETSTAT Restablece las estadísticas.

DBSIZE Devuelve el número de claves en la base de datos


seleccionada.

DEBUG OBJECT key Obtiene información de depuración sobre la clave


dada.

DEBUG SEGFAULT Hace que el servidor se cuelgue.

FLUSHALL Elimina todas las claves de todas las bases de datos.

FLUSHDB Elimina todas las claves de la base de datos actual.

INFO Obtiene información estadística sobre el servidor.

LASTSAVE Obtiene la marca de tiempo UNIX de la última vez que


se guardó correctamente en el disco.

120
© Editorial UOC Capítulo V. Otros aspectos del uso de Redis

Comando Significado

MONITOR Escucha todas las peticiones recibidas por el servidor en


tiempo real.

ROLE Devuelve el rol de la instancia en el contexto de la


replicación.

SHUTDOWN Guarda sincrónamente un conjunto de datos en el


disco y cierra el servidor

SLAVEOF Convierte un servidor en esclavo de otra instancia o lo


promueve como maestro.

SLOWLOG Gestiona el registro de consultas lentas del servidor.

SYNC Comando usado para la replicación.

TIME Retorna el tiempo actual del servidor


Fuente: elaboración propia

Una operación importante del servidor es el proceso de cana-


lización, que consiste en que un cliente puede enviar varias soli-
citudes al servidor sin esperar las respuestas, y finalmente podrá
leerlas todas en un solo paso. Este mecanismo permite mejorar
el rendimiento del sistema.

6.4. Gestión de copias de seguridad

Redis permite realizar copias de seguridad de la base de datos.


Para ello, existe el comando SAVE, el cual crea un archivo deno-
minado dump.rdb con el backup de la base de datos. Para restau-
rar el archivo, hay que situarlo en el directorio de instalación de
Redis y reiniciar el servidor. Para obtener el directorio se usa el
comando CONFIG get dir tal como se muestra en la figura 4.

121
© Editorial UOC Introducción a las bases de datos NoSQL

Figura 4. Obtener directorio

Fuente: elaboración propia

Un comando alternativo es BGSAVE que actúa igual a SAVE


pero se ejecuta en segundo plano.

7. Acceso a Redis usando Python

Redis-py es un cliente en Python para actuar sobre Redis. Para


realizar su instalación basta usar pip:

sudo pip install redis

Para trabajar con el cliente, en primer lugar se crea una cone-


xión (figura 5)

Figura 5. Creación de una conexión

Fuente: elaboración propia

12
© Editorial UOC Capítulo V. Otros aspectos del uso de Redis

A continuación, se pueden invocar comandos usando la cone-


xión que se ha creado. En la figura 6 se muestra un conjunto
de ejemplo de invocación de comandos básicos de creación de
claves y recuperación de los valores almacenados.

Figura 6. Ejemplos de uso

Fuente: elaboración propia

123
© Editorial UOC Introducción a las bases de datos NoSQL

En el siguiente ejemplo de la figura 7 se ilustra el uso del


mecanismo de la canalización. Observemos que, por defecto,
la canalización se ejecuta como una transacción, es decir los
comandos son ejecutados de forma atómica.

Figura 7. Ejemplos de canalización

Fuente: elaboración propia

Si se quiere ejecutar la canalización en modo no transacción


entonces hay que desactivarlo explícitamente cuando se crea:

pipe=r.pipeline(transaction=False)

También es posible usar el mecanismo de publicación/sus-


cripción. Para ello se invoca el método pubsub( ), y se usan los
métodos subscribe(canal) y unsubscribe( ) para suscribirse y
eliminar una suscripción a un canal respectivamente. Cuando
se está suscrito a un canal se pueden recuperar los mensajes
mediante el método get_message( ). El mensaje recuperado está
formado por la siguiente información:

• Tipo: informa sobre el tipo de mensaje, que puede ser «subs-


cribe», «unsubscribe», «psubscribe», «punsubscribe», «messa-
ge», «pmessage».
• Canal: es el canal suscrito o cancelado, o el canal en el que se
publicó un mensaje.

124
© Editorial UOC Capítulo V. Otros aspectos del uso de Redis

• Patrón: es el patrón que coincide con el canal de un mensaje


publicado. Será Ninguno en todos los casos, excepto para
tipos «pmessage».
• Datos: son los datos del mensaje. Con mensajes de tipo
«unsubscribe» o «subscribe», este valor será la cantidad de
canales y patrones a los que se ha suscrito actualmente la
conexión. Con mensajes del tipo pmessages o messages, este
valor será el mensaje publicado real.

En la figura 8, se muestra un ejemplo de uso

Figura 8. Ejemplos de canalización

Fuente: elaboración propia

Si en una aplicación no se quieren recibir los mensajes de con-


firmación de suscripción/cancelación de suscripción, se pueden
ignorar pasando el argumento ignore_subscribe_messages
= True al método r.pubsub ( ). De esta forma los mensajes de
suscripción/cancelación de la suscripción se podrán leer pero no
remitirán confirmación de ejecución.
Hay dos estrategias diferentes para leer los mensajes:

• Usando el método get_message integrado en un bucle. De


esta manera, si hay datos disponibles para leer, get_message ()

125
© Editorial UOC Introducción a las bases de datos NoSQL

los leerá, formateará el mensaje y lo devolverá. Y si no hay


datos para leer, get_message ( ) devolverá inmediatamente
Ninguno.

while True:
mensaje= p.get_message( )
if mensaje:
# Hacer algo con el mensaje

• Usando el método listen ( ). Se trata de un generador que se


bloquea hasta que un mensaje esté disponible.

for mensaje in p.listen( ):


# Hacer algo con el mensaje

En la siguiente dirección se puede encontrar más información


sobre redis-py:
https://redis-py.readthedocs.io/en/latest/

126
© Editorial UOC Capítulo V. Otros aspectos del uso de Redis

Bibliografía
Carlson, J. L. (2013). Redis in action. Manning Publications Co.
Da Silva, M. D.; Tavares, H. L. (2015). Redis Essentials. Packt Publishing
Ltd.
Das, V. (2015). Learning Redis. Packt Publishing Ltd.
Macedo, T., & Oliveira, F. (2011). Redis Cookbook: Practical Techniques for
Fast Data Manipulation. O’Reilly Media, Inc.
Nelson, J. (2016). Mastering Redis. Packt Publishing Ltd.
Redis. Documentation. https://redis.io/documentation.
Redis-py. https://redis-py.readthedocs.io/en/latest/.

127
© Editorial UOC Capítulo VI. Ejemplo de uso de Redis

Capítulo VI
Ejemplo de uso de Redis

1. Introducción

En este capítulo se va a mostrar un ejemplo de cómo se puede


utilizar Redis para crear una aplicación que simula una red social
como Twitter donde se realiza un intercambio de mensajes entre
sus usuarios registrados. Cada usuario puede seguir a otros y
ver los mensajes que han escrito, y de igual forma, un usuario
puede ser seguido por otros usuarios que ven lo que publica. El
presente capítulo está basado en el ejemplo que se desarrolla en
(Carlson, 2013).

2. Elementos de información

Para implementar una red social del tipo propuesto será


necesario gestionar información de unas determinadas enti-
dades. En primer lugar, se necesita almacenar información de
cada usuario registrado en la red y de la actividad que lleva a
cabo en esta. De igual forma, se necesitará almacenar toda la
información acerca de un mensaje publicado, como quién lo
publicó, cuándo, y otros datos. Una información básica que
es necesaria gestionar son los mensajes que han publicado los
usuarios a los que estamos siguiendo. Cuando un usuario se
conecta a su cuenta, lo que espera ver es la lista de mensajes

129
© Editorial UOC Introducción a las bases de datos NoSQL

más recientes p ublicados p or los usuarios a los que sigue.


Igualmente querráevr los últim
os m
ensajes que ha publicado
él m
ism
o yse deberán m antener las relaciones de seguim iento
(seguidores yseguidos)entre usuarios.
Acontinuación, se avn a discutir las necesidades de eprsisten -
cia de cada una de las entidades emncionadas, cuál es el emjor
tipo de datos apra alm acenar la inform ación asociada a dich a
entidad ycóm o se upede imlem
p entar la creación de estas enti -
dades ysu alm acenamiento en eRdis utilizando como lenguaje de
rogram
p ación P
yto
hn.

2.1. Usuario

En general, sería interesante almacenar la siguiente infor-


mación sobre un usuario de una red social similar a Twitter: el
usuario, un nombre, el número de seguidores, el número de per-
sonas a las que sigue, el número de mensajes que ha publicado,
un identificador y cuándo se registró (podría almacenarse más
información de la que aparece aquí listada). Esta información se
podría almacenar como el valor de una clave de tipo HASH. A
continuación, se muestra en Python la función que permite crear
un nuevo usuario.

def crear_usuario(conex, usuario, nombre):


#Se convierte el nombre de usuario a minúsculas para
facilitar las comparaciones.usuario = usuario.lower( )
#Se comprueba que no exista el usuario
if conex.hget(‘usuarios:’, usuario):
return None
#Se incrementa el indentificador de usuario

130
© Editorial UOC Capítulo VI. Ejemplo de uso de Redis

id = conex.incr(‘usuario:id:’)
#Se declara una canalización
pipeline = conex.pipeline(True)
#Se actualiza el hash que mantiene el mapeo entre
usuarios e ids.
pipeline.hset(‘usuarios:’,usuario, id)
#Se añade la información de usuario a una clave de tipo
HASH
pipeline.hmset(‘usuario:%s’%id, {
‘usuario’: usuario,
‘id’: id,
‘nombre’: nombre,
‘seguidores’: 0,
‘siguiendo’: 0,
‘posts’: 0,
‘registro’: time.time( ),
})
pipeline.execute( )
return id

Observar que la inicialización de un usuario consiste en inicia-


lizar a 0 los campos de información, asignarle un valor temporal
al registro, un identificador, definir el nombre del usuario y el
usuario propiamente dicho.

2.2. Mensajes propios

Sobre los mensajes que publican los usuarios de una red social
como Twitter podría interesar almacenar la siguiente informa-
ción: el contenido del mensaje, el nombre e identificador del

131
© Editorial UOC Introducción a las bases de datos NoSQL

usuario que lo upblicó,un identificador p ara el m


ensaje ycuándo
fue upblicado. Esta inform ación se o pdría alm
acenar com o el
avlor de una clave de tip oHSH
A. Acontinuación, se umestra en
yto
Phn la función que eprm
ite crear un nuevo mensaje.

def crear_mensaje(conex, uid, mensaje, **datos):


#Se configura una canalización
pipeline = conex.pipeline(True)
#Se obtiene el usuario asociado al identificador de
usuario uid
pipeline.hget(‘usuario:%s’%uid, ‘usuario’)
#Se crea un nuevo identificador para el mensaje
pipeline.incr(‘mensaje:id:’)
#Se ejecuta la canalización
usuario, id = pipeline.execute( )
#Si no se ha conseguido ningún usuario entonces se
sale
if not usuario:
return None
#Se crea el mensaje
data.update({
‘mensaje’: mensaje,
‘publicado’: time.time( ),
‘id’: id,
‘uid’: uid,
‘usuario’: login,
})
#Se guarda el mensaje creado
pipeline.hmset(‘mensajes:%s’%id, datos)
#Se incrementa el número de mensajes enviados.
pipeline.hincrby(‘usuario:%s’%uid, ‘posts’)

132
© Editorial UOC Capítulo VI. Ejemplo de uso de Redis

#Se ejecuta la canalización


pipeline.execute( )
#Se devuelve el nuevo identificador de mensaje.
return id

2.3. Mensajes de las personas a las que se sigue

Cuando un usuario se autentica en una red social como


Twitter espera poder ver los últimos mensajes que han publicado
los usuarios a los que está siguiendo. En este sentido, el orden de
publicación es básico. Para garantizar este requisito se puede usar
ZSET, un tipo de clave de Redis que preserva el orden de alma-
cenamiento de sus valores. La información que se va almacenar
serán el identificador del mensaje y una marca temporal que
indica el momento en el cual el mensaje se publicó. Este valor
actuará como elemento de ordenación de los mensajes. Aquellos
más recientes de los usuarios a los que se sigue se almacenarán
en un conjunto que se designará con una clave denominada
«recientesseguidores».
A continuación se muestra una función que implementa esta
funcionalidad:

def obtener_mensajes(conex, uid, mensajesrecientes=’re


cientesseguidores:’, pagina=1, num=30):
#Se recuperan los mensajes más recientes de acuerdo
a las dimensiones indicadas
en
#la función.
mensajes = conex.zrevrange(‘%s%s’%(mensajesrecient
es, uid), (pagina-1)*num, pagina*num-1)

133
© Editorial UOC Introducción a las bases de datos N
oSQ
L

#Se crea una canalización


pipeline = conex.pipeline(True)
#Se procesa cada mensaje usando su id
for id in mensajes:
#Se recupera cada mensaje
pipeline.hgetall(‘mensaje:%s’%id)
#Se devuelven los mensajes recuperados y se filtran los
mensajes que han sido
#previamente eliminados.
return filter(None, pipeline.execute( ))

Al recuperar los mensajes almacenados en la clave ZSET,


estos se obtienen en orden cronológico inverso a como fueron
introducidos.
De forma similar, cuando un usuario visita el perfil de otro,
espera encontrarse con los mensajes más recientes enviados por
este. Se trata de un caso particular del que estamos tratando. Es
por ello que, para resolverlo, se utiliza el mismo tipo de clave y la
misma función que se ha implementado. Sin embargo la función
se invocará con el valor «mensajespropios» para el argumento de
«mensajesrecientes» que representan los mensajes más recientes
que han sido publicados por dicho usuario. Hay que tener en cuen-
ta que el problema de gestionar los dos conjuntos de mensajes, se
resuelve nombrando cada conjunto con valores de clave diferente,
«recientesseguidores» para los mensajes más recientes de las per-
sonas que son seguidas, y «recientespropios» para hacer referencia
a los mensajes más recientes de un usuario.

134
© Editorial UOC Capítulo VI. Ejemplo de uso de Redis

2.4. Personas a las que se sigue y personas


seguidas

Para mantener la lista de seguidores y la de las personas a las


que sigue un usuario, se utilizará nuevamente un tipo de datos
ZSET donde se almacenarán los identificadores de los usuarios
y las marcas temporales de cuándo se comenzó la relación de
seguimiento. Asimismo, es importante controlar dos situaciones
extremas, por un lado, cuándo se comienza a seguir a alguien y,
por otro, cuándo se deja de seguir a alguien. En ambos casos,
habrá que hacer modificaciones sobre el tipo HASH que man-
tiene información sobre un usuario, como en el tipo ZSET en
el que se almacena la información de seguidores y seguidos.
Concretamente, habrá que actualizar los valores de las claves que
controlan el número de usuarios seguidores o seguidos, y copiar
o eliminar los mensajes más recientes de la lista de mensajes de
las personas seguidas por un usuario. A continuación, se muestra
el código de la función en Python que implementa lo comentado.

def seguir_usuario (conex, uid, otro_uid):


#Nombre de las claves de seguidores y seguidos
fkey1 = ‘Siguiendo:%s’%uid
fkey2 = ‘Seguidores:%s’%otro_uid
#Se comprueba si el usuario ya está siguiendo al otro
usuario
if conex.zscore(fkey1, otro_uid):
return None
#Se recupera la hora actual
tiempo= time.time( )
#Se declara una canalización.
pipeline = conex.pipeline(True)

135
© Editorial UOC Introducción a las bases de datos NoSQL

#Se añade la relación de seguir al otro usuario en el


correspondiente ZSET
pipeline.zadd(fkey1, otro_uid, tiempo)
#Se añade la relación de ser seguido por el usuario al
correspondiente ZSET
pipeline.zadd(fkey2, uid, tiempo)
#Se recupera el tamaño de los ZSETs correspondiente
pipeline.zcard(fkey1)
pipeline.zcard(fkey2)
#Se recupera los 1000 mensajes más recientes del
nuevo usuario seguido.
pipeline.zrevrange(‘profile:%s’%otro_uid,0,999,
withscores =True)
#Se ejecuta la canalización.
siguiendo, seguidores, idmensajes_marcatemporal =
pipeline.execute( )[-3:]
#Se actualizan el contador del número de usuarios
seguidos en el HASH
pipeline.hset(‘user:%s’%uid, ‘siguiendo’, siguiendo)
#Se actualizan el contador del número de usuarios
seguidores en el HASH
pipeline.hset(‘user:%s’%otro_uid, ‘seguidores’,
seguidores)
#Se comprueba si la lista de pares identificadores de
mensajes y marcas temporales
#recuperados del usuario que se sigue no es vacia
if idmensajes_marcatemporal:
#Se guarda en la lista de mensajes recientes de
seguidores, los pares recuperados
pipeline.zadd(‘home:%s’%uid, **dict(contadores))

136
© Editorial UOC Capítulo VI. Ejemplo de uso de Redis

#Se actualizan los mensajes de la lista de mensajes


más recientes del usuario con los
#1000 primeros mensajes más recientes
pipeline.zremrangebyrank(‘home:%s’%uid, 0, -900)
#Se ejecuta la canalización
pipeline.execute( )
return True

Observemos que la función realiza las siguientes operacio-


nes: añadir los identificadores de los usuarios a los conjuntos
ZSET de seguidores, obtener los tamaños de los conjuntos de
seguidores y de personas seguidas, recuperar los mensajes más
recientes de los usuarios seguidos por un usuario, actualizar la
información del usuario almacenada en una clave de tipo HASH,
y actualizar la lista de mensajes más recientes de las personas
seguidas por un usuario con los mensajes más recientes del
nuevo usuario seguido.
De igual forma, cuando se deja de seguir a alguien habrá que
deshacer las operaciones realizadas: eliminar los identificado-
res de las listas de seguidores y personas seguidas, eliminar los
mensajes más recientes del usuario que se va a dejar de seguir
de la lista de mensajes más recientes de usuarios seguidos por
un usuario y actualizar los contadores de la información de los
usuarios involucrados. En la siguiente función se implementan
estas acciones.

def dejar_seguir_usuario(conex, uid, otro_uid):


#Nombre de las claves de seguidores y seguidos.
fkey1 = ‘Siguiendo:%s’%uid
fkey2 = ‘Seguidores:%s’%otro_uid

137
© Editorial UOC Introducción a las bases de datos NoSQL

#Se comprueba que el usuario que va a dejar de ser


seguid, está en la lista de
#usuarios seguidos.
if not conex.zscore(fkey1, otro_uid):
return None
#Se declara una canalización.
pipeline = conex.pipeline(True)
#Se elimina el usuario que se estaba siguiendo de la
lista de seguidos del usuario.
pipeline.zrem(fkey1, otro_uid)
#Se elimina el usuario seguidor de la lista de usuarios
que siguen a un usuario.
pipeline.zrem(fkey2, uid)
#Se recupera el tamaño de los ZSETs correspondiente
pipeline.zcard(fkey1)
pipeline.zcard(fkey2)
#Se recuperan los mi0 mensajes más recientes del
usuario que se va a dejar de ser
#seguido.
pipeline.zrevrange(‘perfil:%s’%otro_uid,0, 999)
#Se ejecuta la canalización.
siguiendo, seguidores, mensajes = pipeline.execute( )
[-3:]
#Se actualizan el contador del número de usuarios
seguidos en el HASH
pipeline.hset(‘user:%s’%uid, ‘siguiendo’, siguiendo)
#Se actualizan el contador del número de usuarios
seguidores en el HASH
pipeline.hset(‘user:%s’%other_uid, ‘seguidores’,
seguidores)

138
© Editorial UOC Capítulo VI. Ejemplo de uso de Redis

#Se comprueba si la lista de pares identificadores de


mensajes y marcas temporales
#recuperados del usuario que se sigue no es vacia
if mensajes:
#Se eliminan, en la lista de mensajes recientes de
seguidores, los pares recuperados
pipeline.zrem(‘home:%s’%uid, *mensajes)
#Se ejecuta la canalización.
pipeline.execute( )
return True

2.5. Almacenar mensajes de los seguidores

En las funciones anteriores se han consultado los conjuntos


de mensajes más recientes de los usuarios seguidos y del propio
usuario. Sin embargo, no se ha descrito como mantener estos
conjuntos. A continuación se va a considerar esta situación.
Cuando un usuario crea un mensaje, éste se almacena tanto
en el conjunto de mensajes más recientes del usuario como en
el conjunto de mensajes más recientes de usuarios seguidores.
El primer caso no supone ningún problema computacional, sin
embargo, en el segundo caso, habrá que estudiar el número de
seguidores que tiene un usuario, pues puede dar lugar a proble-
mas de eficiencia y de procesamiento. En este sentido, según
estudios estadísticos realizados por Twitter, solo un 1 % de sus
usuarios tienen más de mil seguidores. Es por ello que se van
a tratar dos casos, aquellos usuarios que tienen mil seguidores
o menos y aquellos que tienen más de mil seguidores. Para los
primeros, la actualización del conjunto de mensajes más recientes

139
© Editorial UOC Introducción a las bases de datos NoSQL

de eprsonas seguidas se realizarádirectam ente, im


entras que en
el segundo caso se trataráde o f rm
a diferida.
En la siguiente uf nción se im lem
p enta la actualización del
conjunto de m ensajes ásmrecientes de un usuario yse realiza
una llamada a otra función que se encarga de actualizar el con -
junto de emnsajes ásmrecientes de los usuarios seguidos o pr los
seguidores.

def agregar_propio(conex, uid, mensaje, **data):


#Se recupera el identificador del mensaje creado
id = crear_mensaje(conex, uid, mensaje, **data)
#Si se produce un error se finaliza la función.
if not id:
return None
#Se recupera el momento en que se publicó
publicado= conex.hget(‘mensaje:%s’%id, ‘publicado’)
#Si se produce un error se finaliza la función
if not publicado:
return None
#Se crea la entrada a almacenar en el conjunto de
mensajes más recientes del usuario
post = {str(id): float(publicado)}
#Se añade al conjunto de mensajes más recientes del
usuario.
conex.zadd(‘recientespropios:%s’%uid, **post)
#Se envía la entrada para almacenarla en el conjunto
de mensajes más recientes de
#los seguidores
agregar_seguidores(conex, uid, post)
return id

140
© Editorial UOC Capítulo VI. Ejemplo de uso de Redis

En la siguiente función se implementa la actualización del


conjunto de mensajes más recientes de los usuarios seguidos por
los seguidores.

def agregar_seguidores(conex, uid, post, start=0):


#Se recuperan los siguientes0mil seguidores del usuario
empezando por el último
#usuario que fue actualizado.
seguidores = conn.zrangebyscore(‘seguidores:%s’%u
id, start, ‘inf’,start=0,
num=1000, withscores=True)
#Se inicializa una canalización
pipeline = conn.pipeline(False)
#Se procesa cada seguidor, y se actualiza la variable
start que guardará el último
#usuario actualizado. Esta variable se usará para las
siguientes llamadas a
#agregar_seguidores( )
for seguidor, start in seguidores:
#Se añade el mensaje al conjunto de mensajes más
recientes de los usuarios
#seguidos
pipeline.zadd(‘recientesseguidores:%s’%seguidor,
**post)
#Se divide el conjunto de manera que no sean
demasiado grande
pipeline.zremrangebyrank(‘recientesseguidores:%s’%s
eguidor, 0, -999)
#Se ejecuta la canalización
pipeline.execute( )

141
© Editorial UOC Introducción a las bases de datos NoSQL

#Si se han procesado al menos0mil seguidores entonces


se utiliza la actualización
#retardada
if len(seguidores) >= 1000:
#Ejecución retardada de la actualización del conjunto
de mensajes mas recientes
#de usuarios seguidos
Ejecu_retardada(conex, ‘default’, ‘agregar_seguidores’,
[conex, uid, post, start])

2.6. Eliminación de mensajes

Otra acción habitual que un usuario de una red social como


Twitter realizará es la eliminación de mensajes. Para hacerlo,
habrá que eliminarlo de los valores de la clave de tipo HASH que
los almacena y se deberá actualizar el número de mensajes pos-
teados por un usuario, así como los conjuntos de mensajes más
recientes tanto del usuario como de los usuarios que lo siguen.
En la siguiente función se muestra como se implementa está
operación.

def borrar_mensaje(conex, uid, mensaje_id):


#Nombre de la clave del mensaje
clave = ‘mensaje:%s’%mensaje_id
#Se recupera el identificador de usuario del propietario
del mensaje
if conex.hget(clave, ‘uid’) != str(uid):
return None
#Se abre una canalización
pipeline = conex.pipeline(True)

142
© Editorial UOC Capítulo VI. Ejemplo de uso de Redis

#Se elimina el mensaje con la clave dada


pipeline.delete(clave)
#Se actualiza el conjunto de mensajes más recientes
del propio usuario
pipeline.zrem(‘recientespropios:%s’%uid, mensaje_id)
#Se actualiza el conjunto de mensajes más recientes de
los seguidores
pipeline.zrem(‘recientesseguidores:%s’%uid, mensaje_
id)
Disminuye el contador de mensajes posteados de la
información de usuario
pipeline.hincrby(‘usuario:%s’%uid, ‘posts’, -1)
#Se ejecuta la canalización
pipeline.execute( )
return True

3. Conclusión

En este capítulo se ha presentado un ejemplo de aplicación


de Redis. Tal como se ha mostrado, la riqueza de tipos de clave
que ofrece permite, de una manera fácil y simple, implementar el
modelo de datos que una red social como Twitter requiere para
poder funcionar. Si se compara en líneas de código, este sería
bastante más elevado si se utilizara como sistema de persistencia
una base de datos relacional. Por ejemplo, el almacenamiento
ordenado de la información, o simplemente la recuperación de
los datos requeriría de costosas consultas sobre las tablas.
Por otro lado, se puede observar que en el ejemplo expuesto
se han implementado las funciones más básicas, sin embargo,

143
© Editorial UOC Introducción a las bases de datos N
oSQ
L

existen algunas funciones que no se han considerado y que


podrían implementarse de una manera similar tales como:

• La gestión de los retweets.


• Los mensajes que se etiquetan como que gustan a un usuario
concreto.
• La posibilidad de tener grupos de usuarios privados.
• La posibilidad de replicar mensajes y generar hilos de conver-
saciones.
• La posibilidad de etiquetar los mensajes con hashtags.
• Mantener un registro de las personas que mencionan a alguien.
• Disponer de controles de spam o de abusos realizados por
usuarios.

Cualquiera de estas funciones podrían ser implementadas de


una manera simple usando funciones y estructuras de informa-
ción semejantes.
En la siguiente dirección de la documentación de Redis,
http://cort.as/-F2xX, se puede encontrar otra implementación
similar de la red social Twitter utilizando el lenguaje PHP. Esta
red se denomina retwis, y existe tanto una demo online de demos-
tración en la dirección http://cort.as/-F2xb como el acceso libre
al código PHP que implementa la red en la dirección http://cort.
as/-F2xe.

144
© Editorial UOC Capítulo VI. Ejemplo de uso de Redis

Bibliografía
Carlson, J. L. (2013). Redis in action. Manning Publications Co.

145
© Editorial UOC Conclusión

Conclusión

En este libro se ha pretendido realizar una introducción a


los principales conceptos de las bases de datos NoSQL, y su
ilustración en un tipo concreto de la llamada familia de bases de
datos de clave-valor. Este tipo de bases de datos se engloba en
las denominadas bases de datos orientadas hacia agregados. Se
caracterizan porque la unidad de almacenamiento es una entidad
denominada agregado que representa una estructura de datos
compleja parecida a las estructuras que se gestionan en los len-
guajes de programación.
En el caso concreto de las bases de datos de tipo clave-valor,
el agregado es un valor opaco en el sentido de que su contenido
no es accesible desde la propia base de datos. Es necesario recu-
perar el valor almacenado en esta a partir de una clave asociada
al agregado, y ya desde fuera se puede acceder a dicho contenido.
Este mecanismo puede parecer limitado en algún aspecto, como
la imposibilidad de realizar consultas basadas en los contenidos
de los agregados. Sin embargo presenta como ventaja la riqueza
de posibles valores que pueden ser almacenados. Esta caracte-
rística permite usar esta base de datos en muchos ámbitos. Es
importante destacar la semejanza que tienen este tipo de bases
de datos con las bases de datos documentales, las cuales pueden
simular el comportamiento de una base de datos de tipo clave-
valor aunque con la principal diferencia de que en las documen-
tales sí se pueden plantear consultas basadas en los contenidos
de los agregados.

147
© Editorial UOC Introducción a las bases de datos NoSQL

El segundo objetivo del libro era realizar una introducción a


Redis como base de datos de tipo clave-valor. Para ello, en primer
lugar, se ha descrito como se realiza su instalación. Se ha des-
crito el modelo de datos y la arquitectura que soporta esta base
de datos, y se han introducido los diferentes tipos de claves que
posee. Este último aspecto es importante, dado que Redis ofre-
ce una variedad y riqueza de tipos de clave que permite realizar
mapeos con las estructuras de datos utilizadas en los lenguajes de
programación. Asimismo se han ilustrado varios de los aspectos
comunes a las bases de datos NoSQL tales como son la replica-
ción y particionamiento de la información y los mecanismos de
persistencia de la información. Por otra parte, también se han
introducido otros aspectos de Redis, tales como el sistema de
mensajería, el sistema transaccional, el lenguaje de scripting Lua o
el uso del lenguaje Python para poder interactuar con ella.
Por último, se ha querido mostrar un ejemplo de aplicación
de Redis en un caso real y se ha descrito como se implementaría
una red social similar a Twitter. Se ha mostrado una implemen-
tación de las funcionalidades más básicas, pero su extensión
completa se podría hacer de una forma tan simple como la que
se ha mostrado.
El libro tiene la pretensión de ser un punto de partida para
aquellos que quieren profundizar en las bases de datos NoSQL y
en particular en la base de datos Redis.

148
TECNOLOGÍA

En este libro se ofrece una introducción a las bases de datos NoSQL utilizando
como elemento de ilustración Redis, una base de datos de tipo clave-valor.
Se estructura en dos partes. En la primera, se describen los conceptos
fundamentales de las bases de datos NoSQL, y en la segunda, se introduce Redis.
Se explica su instalación, el modelo y las estructuras de datos, aspectos sobre
replicación, particionamiento y tipos de persistencia, y algunos aspectos de
administración de Redis. En el último capítulo se describe un ejemplo
de aplicación real de este sistema.

Con este libro aprenderás sobre:

bases de datos NoSQL; Redis; big data; análisis de datos;


bases de datos orientadas a agregados; particionamiento;
replicación; bases de datos clave-valor; Lua scripting;
almacenamiento no tradicional

Antonio Sarasa
Doctor en Informática por la Universidad
Complutense de Madrid, donde imparte
docencia. Sus áreas de investigación se
centran en la aplicación de las técnicas
de procesadores de lenguajes y compiladores
al desarrollo de aplicaciones.

También podría gustarte