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

Familiarícese con la base de datos de Redis:iteración de claves

Una de las cosas que a menudo confunde a los usuarios que están familiarizados con otras bases de datos cuando prueban Redis es la falta de visibilidad de la base de datos:no hay un conjunto de tablas o colecciones para mira, solo un espacio de clave simple y plano que podría (potencialmente) tener millones de claves. La capacidad de iterar de forma económica sobre este espacio clave se vuelve muy importante para familiarizarse con el contenido de la base de datos.

La iteración sobre el espacio de claves de Redis tiene otros casos de uso importantes, algunos de los que se me ocurren son:

  • recolección de basura o limpieza de claves que coincidan con un determinado patrón
  • movimiento de datos y cambios de esquema o movimiento de un determinado conjunto de claves a otra estructura de datos
  • depuración, muestreo de datos, corrección de datos o búsqueda y reparación de todas las claves que se estropearon debido a un cambio reciente

En esta publicación, profundizaremos en varias opciones de iteración de espacio clave disponibles en Redis.

Iteradores O(N):CLAVES

El comando KEYS de Redis devuelve todas las claves de la base de datos que coinciden con un patrón (o todas las claves del espacio de claves). Los comandos similares para obtener todos los campos almacenados en un hash son HGETALL y para obtener todos los miembros de SMEMBERS. Las claves en Redis se almacenan en un diccionario (también conocido como tabla hash). El comando KEYS funciona iterando sobre este diccionario y enviando todo lo que coincide con el patrón como una sola respuesta de matriz. Los otros comandos funcionan de manera similar.

El rendimiento de tal operación depende del tamaño de la colección, es decir, O(N). Por lo tanto, se desaconseja encarecidamente el uso de KEYS en entornos de producción con una gran cantidad de claves. Redis, al ser de un solo subproceso, se bloquea durante esta iteración, lo que bloquea otras operaciones. Por lo tanto, KEYS debe usarse solo para la depuración y otras ocasiones especiales en las que el rendimiento no es una preocupación (como cuando la base de datos se desconectó para aplicar una corrección de datos). La otra cosa importante para recordar acerca de este algoritmo es que envía todas las claves coincidentes juntas como una sola respuesta. Esto puede ser extremadamente conveniente cuando el espacio de claves es pequeño pero creará múltiples problemas en un espacio de claves grande. Sin embargo, KEYS es un comando favorito entre los desarrolladores en sus propios entornos de desarrollo.

CLAVES en acción:

127.0.0.1:6379[1]> MSET one 1 two 2 three 3 four 4
OK
# All the keys
127.0.0.1:6379[1]> keys *
1) "four"
2) "three"
3) "two"
4) "one"
# keys that begin with the letter 't'
127.0.0.1:6379[1]> keys t*
1) "three"
2) "two"
# keys that have a 'ee' in them
127.0.0.1:6379[1]> keys *ee*
1) "three"

Iteradores basados ​​en cursores:SCAN

El SCAN y sus comandos hermanos, SSCAN (para conjuntos), HSCAN (para hash) y ZSCAN (para conjuntos ordenados) proporcionan el enfoque basado en el cursor para iterar sobre las estructuras de datos de Redis. Han estado disponibles en Redis desde 2.8.0.

Las claves se devuelven en iteraciones incrementales con garantía de tiempo constante para cada iteración. Se devuelve un cursor (un número entero en este caso) cuando se inicializan las iteraciones y se devuelve un cursor actualizado en cada iteración. Un ciclo de iteración comienza cuando el cursor se establece en 0 en la solicitud SCAN y finaliza cuando el cursor devuelto por el servidor es 0.  Debido a los matices de la arquitectura de Redis y la implementación del algoritmo del cursor, aquí hay algunas peculiaridades de este enfoque:

  • Una iteración completa siempre recupera todos los elementos que estaban presentes en la colección desde el principio hasta el final de una iteración completa.
  • Una iteración completa nunca devuelve ningún elemento que NO estuviera presente en la colección desde el principio hasta el final de una iteración completa.
  • Un elemento dado puede devolverse varias veces. Depende de la aplicación manejar el caso de elementos duplicados
  • Los elementos que no estuvieron constantemente presentes en la colección durante una iteración completa, pueden devolverse o no:no está definido.
  • La cantidad de elementos devueltos durante cada conteo varía y también puede ser 0. Sin embargo, la iteración no se completa hasta que el servidor devuelve el valor del cursor de 0.
  • El CONTADOR La opción se puede utilizar para limitar el número de elementos devueltos en cada iteración. El valor predeterminado es 10. Sin embargo, se considera solo una sugerencia y no se aplica en todos los casos. El valor COUNT se puede cambiar durante cada llamada de iteración.
  • El PARTIDO La opción permite especificar patrones como lo permite el comando KEYS.
  • La implementación del cursor no tiene estado en el lado del servidor. Eso permite (potencialmente) iteraciones infinitas para comenzar en paralelo. Además, no hay requisitos para garantizar que una iteración continúe hasta el final y se pueda detener en cualquier momento.

A pesar de sus peculiaridades, ESCANEAR es un comando muy útil y el comando correcto para elegir iteraciones de espacio clave para la mayoría de los casos de uso.

ESCANEAR es un comando muy útil y el comando correcto para elegir iteraciones de espacio clave en #RedisClick To Tweet

ESCANEAR en acción

127.0.0.1:6379[1]> flushdb
OK
127.0.0.1:6379[1]> keys *
(empty list or set)
127.0.0.1:6379[1]> debug populate 33
OK
127.0.0.1:6379[1]> scan 0 COUNT 5
1) "4"
2) 1) "key:1"
   2) "key:9"
   3) "key:13"
   4) "key:29"
   5) "key:23"
127.0.0.1:6379[1]> scan 4 
1) "42"
2)  1) "key:24"
    2) "key:28"
    3) "key:18"
    4) "key:16"
    5) "key:12"
    6) "key:2"
    7) "key:6"
    8) "key:31"
    9) "key:27"
   10) "key:19"
127.0.0.1:6379[1]> scan 42
1) "9"
2)  1) "key:3"
    2) "key:4"
    3) "key:20"
    4) "key:8"
    5) "key:32"
    6) "key:5"
    7) "key:26"
    8) "key:10"
    9) "key:21"
   10) "key:14"
127.0.0.1:6379[1]> scan 9 COUNT 100
1) "0"
2) 1) "key:25"
   2) "key:30"
   3) "key:22"
   4) "key:17"
   5) "key:15"
   6) "key:0"
   7) "key:11"
   8) "key:7"

Bajo el capó

El algoritmo que SCAN (y sus comandos hermanos) usan para escanear es intrigante y conduce a algunas de las características del comando que describimos anteriormente. Antirez lo describió a un alto nivel en su publicación de blog y se explica (ligeramente mejor) en los comentarios sobre la implementación (función dictScan). Describirlo en detalles hará que esta publicación sea demasiado larga, así que daré suficiente descripción para que sus implicaciones sean evidentes.

  • La mayoría de las estructuras de datos de Redis se representan internamente como diccionarios (al menos parcialmente en el caso de conjuntos ordenados). Se implementan como tablas hash de potencia de dos con encadenamiento para colisiones. El desafío de escribir un algoritmo iterativo basado en cursor aquí es poder lidiar con el crecimiento y la reducción del hash sin sacrificar los principios de Redis de simplicidad (de la API) y velocidad.
  • SCAN básicamente escanea un montón de cubos de hash en cada iteración y devuelve los elementos que coinciden con el patrón en esos. Dado que solo observa una lista fija de cubos, es posible que algunas iteraciones no devuelvan ningún valor.
  • El cursor que se devuelve es básicamente un desplazamiento en la tabla hash que se está iterando. Se ocupa del crecimiento y la reducción de las tablas hash (es decir, el rehashing) mediante la manipulación inteligente de los bits de nivel superior del desplazamiento mientras aumenta el desplazamiento junto con las propiedades de la tabla hash. Las implicaciones de este enfoque son que los nuevos elementos agregados durante la iteración pueden devolverse o no. Sin embargo, el cursor en sí no necesitaría reiniciarse con un cambio en el tamaño de la tabla hash.
  • Un depósito determinado debe visitarse solo una vez y todas sus claves deben devolverse de una sola vez. Esto es nuevamente para garantizar que el cambio de tamaño de hash (es decir, el rehashing) no complique el progreso de la iteración. Sin embargo, esto lleva a que el argumento COUNT no sea estrictamente ejecutable.
  • Dado que el enfoque anterior no tiene estado en el lado del servidor, básicamente implica que las iteraciones se pueden detener o se puede iniciar una gran cantidad de iteraciones en paralelo sin aumentar el uso de la memoria.

Resumen

En un nivel alto, hay dos opciones disponibles para iterar sobre el espacio clave de Redis:

  1. Use KEYS cuando el rendimiento no sea una preocupación o cuando el espacio de claves tenga un tamaño razonable.
  2. En cualquier otro momento, use ESCANEAR.
Para iterar sobre el espacio de claves de #Redis, use KEYS cuando el rendimiento no sea una preocupación; de lo contrario, use SCANClick To Tweet

¿Sabía que ahora admitimos hosting para Redis™*? Obtenga alojamiento completamente administrado para Redis™ en la seguridad de su propia cuenta en la nube y aproveche los créditos de AWS/Azure para sus implementaciones de Redis™.