sql >> Base de Datos >  >> NoSQL >> Redis

Introducción a las estructuras de datos de Redis:conjuntos

Redis (Servidor de diccionario remoto) es un almacén de clave-valor en memoria inmensamente popular que también ofrece durabilidad opcional, creación de particiones, replicación y muchas otras funciones. Actualmente es la base de datos clave-valor más popular y es conocida por su simplicidad, su bajo consumo de memoria y su baja curva de aprendizaje. Redis también se conoce como servidor de estructura de datos y es compatible con operaciones atómicas en estructuras de datos como hashes, listas, conjuntos, conjuntos ordenados, mapas de bits e hiperloglogs. En esta publicación, veremos el tipo de datos establecido proporcionado por Redis junto con su uso y casos de uso de la vida real.

Conjuntos Redis

Los conjuntos de Redis son colecciones desordenadas de cadenas (una cadena es el valor básico de Redis que puede contener casi cualquier cosa) que proporciona comprobaciones constantes de adición, eliminación y membresía. Redis también admite operaciones de unión, intersección y resta razonablemente rápidas entre conjuntos. Como era de esperar, no permite valores repetidos.

Estos son algunos ejemplos de conjuntos de Redis en acción de redis-cli . Aquí hay un resumen de las representaciones clave en el siguiente ejemplo:

  • usuarios:todos representa un conjunto de todos los usuarios registrados en un sitio web.
  • usuarios:actv representa a los usuarios activos.
  • usuarios:inactv representa a los usuarios inactivos (usuarios que no han visitado el sitio durante un tiempo).
# sadd key member [member ...] : add members to a set
127.0.0.1:6379> sadd users:all 11 12 13 14 15 Rocket Pocket Socket
(integer) 8
127.0.0.1:6379> type users:all
set
# smembers key: get all members of a set
127.0.0.1:6379> smembers users:all
1) "Pocket"
2) "11"
3) "Socket"
4) "13"
5) "14"
6) "Rocket"
7) "12"
8) "15"
# sismember key member: is the given value a member of the set?
127.0.0.1:6379> sismember users:all 00
(integer) 0
127.0.0.1:6379> sismember users:all 11
(integer) 1
127.0.0.1:6379> sismember users:all Socket
(integer) 1
127.0.0.1:6379> sadd users:inactv 11 12 13
(integer) 3
# sinter key [key ...]: Intersection of multiple sets
# Similar: sinterstore stores the result of intersection of sets to a new set
127.0.0.1:6379> sinter users:all users:inactv
1) "11"
2) "12"
3) "13"
# scard key: cardinality of the set i.e. number of members present in the set
127.0.0.1:6379> scard users:all
(integer) 8
# sdiff key [key ...] : Subtract multiple sets
# Similar: sdiffstore: subtract and store result in a new destination set
127.0.0.1:6379> sdiff users:all
1) "Pocket"
2) "11"
3) "Socket"
4) "13"
5) "14"
6) "12"
7) "Rocket"
8) "15"
127.0.0.1:6379> sdiff users:all users:inactv
1) "14"
2) "Pocket"
3) "Rocket"
4) "Socket"
5) "15"
# sdiffstore destination key [key ...]
127.0.0.1:6379> sdiffstore users:actv users:all users:inactv
(integer) 5
127.0.0.1:6379> smembers users:actv
1) "14"
2) "Pocket"
3) "Rocket"
4) "Socket"
5) "15"
127.0.0.1:6379> sdiff users:all users:actv users:inactv
(empty list or set)
# smove source destination member: move a member from source set to destination.
127.0.0.1:6379> smove users:inactv users:actv 11
(integer) 1
127.0.0.1:6379> smembers users:actv
1) "Pocket"
2) "11"
3) "Socket"
4) "14"
5) "Rocket"
6) "15"

Otros comandos de conjunto importantes incluyen:

  • SUNION:conjunto de unión
  • SPOP:elimina aleatoriamente un elemento
  • SREM:eliminar uno o más elementos

La lista completa de comandos de Redis relacionados con el conjunto se puede encontrar aquí.

Conceptos internos de Redis

Redis almacena conjuntos internamente como diccionarios. Los diccionarios en Redis se implementan como tablas hash que usan la función hash MurmurHash2 y crecen a través del cambio de tamaño incremental. Las colisiones hash se manejan mediante el encadenamiento. Los conjuntos tienen una codificación especial para conjuntos pequeños cuando todos los miembros de un conjunto están en base 10 en el rango # de enteros con signo de 64 bits llamados IntSets. Esto es esencialmente una matriz ordenada de enteros. Las búsquedas dentro de la matriz se realizan mediante búsqueda binaria. Obviamente, esta implementación es eficiente para conjuntos muy pequeños. El tamaño hasta el que se utiliza esta codificación se rige por set-max-intset-entries parámetro de configuración. El valor predeterminado es 512. Puede encontrar una buena descripción de las estructuras de datos internas utilizadas por Redis aquí.

Aplicaciones Redis

Esta es una pequeña lista de algunas de las posibles aplicaciones de Redis Set:

  • Como conjunto, se puede usar para rastrear elementos únicos:
    • Todas las direcciones IP únicas que visitan su sitio.
    • Todas las instancias de trabajos únicos actualmente en un estado determinado, etc.
  • Nuevamente, como conjunto, se puede usar para denotar como "pertenece a" o una relación similar:
    • Todos los SKU que pertenecen a una categoría en particular.
    • Todos los objetos con una etiqueta particular, etc.
  • Los conjuntos solo se pueden usar para combinar relaciones, es decir, unión/intersección/resta de conjuntos:
    • Todos los SKU que pertenecen a la categoría de camisetas, pero no a una subcategoría de cuellos de polo.

Tomemos un ejemplo de la vida real y exploremos más casos de uso relacionados.

Visual Profiler para su tienda de libros electrónicos

Digamos que es el propietario de una librería en línea muy grande que enumera millones de títulos. Su base de datos principal es MongoDB y funciona bastante bien para la mayoría de sus casos de uso con el uso correcto de indexación, fragmentación, etc. Aquí hay un esquema de documento de base de datos parcial para los libros colecciones:

...
sku: SKU,
pid: Product ID,
title: String,
auth: String,
pub: String,
isbn: ISBN,
edition: Int,
price: Float,
rating: Float,
cats: [String, String ...],
tags: [String, String ...],
...

También registra transacciones en una colección llamada txns que puede parecerse a:

txnid: TxnID,
cid: CustomerID,
amnt: Float,
curr: Currency,
sku: [sku1, sku2, ...],
time: TimeStamp,
...

Y una colección de vistas llamada views:

time: TimeStamp, # daily aggregated
cid: CustomerID,
sku: [sku1, sku2, ...],
...

Obviamente, este es un ejemplo muy simplificado que hace suposiciones amplias. Nuestra intención es mostrar un ejemplo de conjunto de Redis en un escenario (casi) del mundo real.

Bien, ahora usted, como gerente de la tienda, desea una herramienta Visual Profiler para analizar las relaciones y el comportamiento de los clientes en diferentes categorías. Por ejemplo:

  • ¿Cuál es la categoría más popular?
  • ¿La gente que mira o compra ciencia ficción también mira no ficción?

Quieres poder hacer esto en tiempo real, es decir, la interfaz de usuario del generador de perfiles marcará casillas, botones que te permitirán cambiar parámetros y ver los resultados (casi) inmediatamente.

Hacer tales operaciones en MongoDB implicará realizar consultas bastante complicadas para unir varias categorías, etiquetas y otros datos que podrían interesarle. Con un conjunto de trabajo que no cabe en la memoria, estas no serían las operaciones más rápidas. Por ejemplo:

  • Encontrar todos los libros vendidos hoy que eran ficción, pero no ciencia ficción, implicará consultar el txn recopilación de las transacciones de hoy. Luego, iterar sobre los SKU para recopilar sus categorías y luego realizar operaciones $in/$nin.

Veamos cómo se manejaría esto incorporando Redis a la mezcla. Al final de cada día, los trabajos programados diarios pueden ejecutarse en estas colecciones de MongoDB para crear conjuntos de Redis. El tipo de conjuntos que desee crear dependerá del tipo de filtros que desee admitir en su interfaz. Por ejemplo, supongamos que le gustaría admitir consultas relacionadas con categorías, queremos crear conjuntos como:

cat:type:catID
cat:sku:fiction
cat:sku:nonfiction
cat:sku:scfiction
cat:sku:history
cat:sku:milhistory
cat:sku:military
...
cat:cid:fiction
cat:cid:nonfiction
cat:cid:scfiction
cat:cid:history
cat:cid:milhistory
cat:cid:military
...

Los conjuntos cat:sku:* contendrán SKU de libros vendidos/vistos hoy en esa categoría. De manera similar, cat:cid:* contendrá el CID de los clientes que compraron/vendieron libros en esa categoría. Una muestra de las consultas que podemos responder con estos conjuntos son:

  • Clientes (o número de clientes) que vieron/compraron libros de Ficción (categoría única) hoy:smembers cat:cid:fiction
  • Clientes que vieron/compraron History pero no Military History hoy:sdiff cat:cid:history cat:cid:milhistory
  • (Número de) libros vendidos hoy que eran de ciencia ficción y militar, es decir, ciencia ficción militar:sinter cat:sku:scfiction cat:sku:military
  • Cualquier cantidad de operaciones de unión, intersección y diferencia que le interesen.

Esto en sí mismo nos brinda capacidades de consulta muy poderosas. ¡Agreguemos más conjuntos! Digamos que creamos conjuntos adicionales basados ​​en calificaciones de libros. Por ejemplo:

rat:sku:5str: Set of books with ratings > 4.5
rat:sku:4str: Set of books with ratings > 3.5 && <= 4.5
rat:sku:3str: ...
rat:sku:2str: ...
...
rat:cid:5str: Set of customer who bought books with ratings as mentioned above.
rat:cid:4str: ...
..

Equipado con estos conjuntos, ahora puede descubrir rápidamente cosas como:

  • Libros de ficción calificados con 4 estrellas o más comprados hoy:  sunionstore rat:sku:4strabv rat:sku:5str rat:sku:5str/sinter rat:sku:4strabv cat :sku:ficción
  • Cliente que compró libros de 3 estrellas y superiores en la historia:sunionstore rat:cid:5strabv rat:cid:3str rat:cid:5str rat:cid:5str/sinter cat:cid:historia rat:cid:5strabv

Ahora, supongamos que desea enviar un cupón de descuento a todos sus clientes que compraron un libro de Astrología hoy con una calificación de 2 o menos (como disculpa por la mala experiencia de tener que leer ese libro!). Puede exportar esa lista de CustomerID s y envíelo a su aplicación de correo electrónico. Del mismo modo, puede crear conjuntos para otras cosas que desee exponer como filtros en su Visual Profiler, como etiquetas, rangos de precios, etc.

Las ventajas de usar Redis Sets son obvias aquí. La tienda en memoria conducirá a un acceso realmente rápido para que la interfaz se sienta ágil. Además, las operaciones de conjuntos de Redis son de tiempo constante o lineales.

Conclusión

En esta publicación, presentamos con ejemplos una de las estructuras de datos de Redis más útiles:los conjuntos. Estas son algunas de nuestras otras publicaciones en la serie de estructuras de datos de Redis:

  • Hashes de Redis
  • Mapas de bits de Redis
  • Conjuntos Redis
  • Conjuntos ordenados de Redis