Comandos Escanear y Teclas de redis

antecedentes

  • Tenemos un centro de usuarios similar, en el que millones de usuarios se almacenan en redis con user_id + id number como clave. Existe el requisito de utilizar user_ como prefijo para que la consulta coincidente coincida con la clave. Cuando se ejecuta este comando de operación, el servicio se congela y redis tiene algunos tiempos de espera de enlace. El problema encontrado en la última fila es el problema causado por demasiadas claves encontradas en las claves. La razón específica es del principio de su orden.
  • La solución final es: use el comando de escaneo

Llaves

Introducción

  1. La coincidencia aproximada se puede realizar mediante una simple regularización, sin paginación, sin cursor. Es búsqueda y recorrido de fuerza bruta.
  2. La ventaja es la conveniencia y las únicas desventajas. Redis es de un solo subproceso, es decir, si hay demasiadas consultas en mi subproceso, lo que lleva a un tiempo de consulta prolongado, otros subprocesos se bloquearán o expirarán. La complejidad de tiempo de la consulta es O (n)

Escanear

Introducción

  1. La complejidad del escaneo es O (n), y el cursor se puede usar para consultas paso a paso sin bloquear hilos
  2. La coincidencia aproximada se puede realizar de la misma manera que las teclas, pero cada vez que tenga que traer un cursor devuelto, puede usar limit para limitar el número máximo de entradas, que puede ser menor pero no mayor que (http://doc.redisfans.com/key/scan .html # escaneo)
  3. Los datos devueltos por el cursor pueden estar vacíos o más de uno cada vez. Siempre que el cursor devuelto no sea 0, no significa que los datos se hayan ido.
  4. Pero todavía hay un problema, es decir, es posible devolver valores de clave duplicados. Esto requiere que nuestra aplicación realice una deduplicación. Puede usar set para almacenamiento o Map
    porque las dos estructuras de datos en sí mismas no se pueden repetir.

Exploración interna de SCAN

  1. El redis global usa almacenamiento de valor clave y usa su diccionario de dict de estructura de datos subyacente. El almacenamiento interno del diccionario es similar al hashmap en Java, y su capa inferior se realiza a través de matrices y listas vinculadas.

  2. La clave que almacenamos en el dict es el subíndice de la matriz a continuación, y la siguiente tabla de la matriz se obtiene calculando el valor hash. Es precisamente por el conflicto de hash que existe una lista vinculada.

  3. Cuando se utiliza la exploración, el cursor de exploración es el subíndice de la matriz. Debido a que el almacenamiento se realiza después de calcular el hash, no se almacena secuencialmente en la matriz, por lo que puede haber o no un valor en una sección de la matriz. valor. También es posible que haya varios valores en una ranura. Entonces, esta es la razón por la que hay escaneos múltiples y cero en el proceso incremental, como se muestra a continuación
    [Error en la transferencia de la imagen del enlace externo. El sitio de origen puede tener un mecanismo de enlace anti-sanguijuela. Se recomienda guardar la imagen y subirla directamente (img-YrSOvyHH-1598970383675) (http://note.youdao.com/yws/res/20441/B47D5C36549948FE8A15FE8C9854E10C)]

  4. Si es conveniente seguir el orden de los subíndices de la matriz, ¿qué deberíamos hacer si expandimos, porque después de la expansión, necesitamos volver a aplicar el hash y la posición de los subíndices de la matriz cambiará. Luego, en este proceso, el cursor devuelto por escaneo antes de expandir no es exacto ¿Todavía?

  5. La solución de Redis para la expansión de la tabla siguiente es : en lugar de atravesar desde el bit 0 de la matriz de primera dimensión hasta el final, utiliza
    la adición de acarreo de orden superior para atravesar. La razón para usar un método tan especial para el recorrido es
    evitar la duplicación y la omisión del recorrido de la ranura cuando se considera la expansión y contracción del diccionario .

  6. La razón principal para elegir la adición de acarreo de bits altos son sus características de expansión. Es similar a hashMap. Utiliza :
    * HashMap en Java tiene el concepto de expansión. Cuando loadFactor alcanza el umbral, necesita reasignar una nueva
    matriz del doble del tamaño. , Y luego refrito todos los elementos a la nueva matriz. Rehash es la
    operación de módulo del valor hash del elemento a la longitud de la matriz. Debido a que la longitud ha cambiado, la ranura donde se adjunta cada elemento también puede haber cambiado
    . Y debido a que la longitud de la matriz es 2 n ( la razón por la que su capacidad es 2 n cuando expandimos ), la operación de módulo es equivalente a la operación de bit Y
    Inserte la descripción de la imagen aquí

En términos abstractos, asumiendo que el número binario de la ranura inicial es xxx, entonces los elementos en la ranura se volverán a
aplicar a 0xxx y 1xxx (xxx + 8). Si la longitud del diccionario se amplía de 16 bits a 32 bits,
los elementos de la ranura binaria xxxx se volverán a aplicar a 0xxxx y 1xxxx (xxxx + 16). *

a mod 8 = a & (8-1) = a & 7
a mod 16 = a & (16-1) = a & 15
a mod 32 = a & (32-1) = a & 31

La siguiente figura es una comparación de contracción y expansión.
Inserte la descripción de la imagen aquí

Entonces, redis usa una adición de acarreo de orden superior para atravesar.

return (key == null) ? 0 : (h = key.hashCode()) ^ (h >>> 16); Java 1.8计算hash的方法
  1. Además, durante la expansión, se realizarán copias y refrito, y la cantidad de datos en redis será grande, por lo que un refrito único provocará un problema de bloqueo. Entonces, redis usa refrito progresivo. En otras palabras, el refrito no se realiza a la vez, sino que se continúa lentamente, por lo que esto también es algo a lo que hay que prestar atención durante el proceso de escaneo, es decir, se escanean tanto los dictados nuevos como los antiguos, y finalmente se fusionan y se devuelven.
  2. Podemos volver a pensar en las claves. ¿No es necesario que consideremos las cuestiones anteriores? , Porque siempre escanea la cantidad completa cada vez, por lo que no se preocupa por la expansión.

para resumir

  1. Uso de teclas y escaneo de redis
  2. Introducción al escaneo interno
  3. La estructura de datos básica de dict y el proceso general de expansión

referencia


Referencia de comando reids " Redis Deep Adventure" : http://doc.redisfans.com/key/scan.html#scan

Supongo que te gusta

Origin blog.csdn.net/weixin_40413961/article/details/108352131
Recomendado
Clasificación