¿Cómo lidiar con la gran clave de Redis?

Hola a todos, soy Xiaolin.

Hablemos hoy sobre cuatro preguntas sobre la gran clave de Redis.

  • ¿Qué es una llave grande de Redis?
  • ¿Qué problemas pueden causar las teclas grandes?
  • ¿Cómo encontrar la llave grande?
  • ¿Cómo eliminar la clave grande?

¿Qué es una llave grande de Redis?

Una clave grande no significa que el valor de la clave sea grande, sino que el valor correspondiente a la clave sea grande.

En términos generales, las siguientes dos situaciones se denominan grandes claves:

  • Los valores de tipo String son mayores de 10 KB;
  • El número de elementos de tipo Hash, List, Set, ZSet supera los 5000;

¿Qué problemas pueden causar las teclas grandes?

La llave grande traerá los siguientes cuatro efectos:

  • El cliente agotó el tiempo de espera y se bloqueó . Dado que Redis ejecuta comandos en un proceso de subproceso único y lleva tiempo operar teclas grandes, Redis se bloqueará. Desde la perspectiva del cliente, no hay respuesta durante mucho tiempo.
  • causar congestión en la red . Cada vez que se adquiere una clave grande, el tráfico de red es relativamente grande, si el tamaño de una clave es de 1 MB y el número de visitas por segundo es de 1000, entonces se generarán 1000 MB de tráfico por segundo, lo cual es catastrófico para un servidor con una tarjeta de red gigabit normal.
  • Bloquear subprocesos de trabajo . Si usa del para eliminar una clave grande, el subproceso de trabajo se bloqueará, por lo que no hay forma de procesar los comandos posteriores.
  • La memoria está distribuida de manera desigual . En el modelo de clúster, cuando la fragmentación de ranuras es uniforme, habrá datos y consultas sesgadas.Algunos nodos de Redis con claves grandes ocupan mucha memoria, y el QPS será relativamente grande.

¿Cómo encontrar la llave grande?

1. redis-cli --bigkeys para encontrar claves grandes

Puede encontrar claves grandes con el comando redis-cli --bigkeys:

redis-cli -h 127.0.0.1 -p6379 -a "password" -- bigkeys

Precauciones al usar:

  • Lo mejor es optar por ejecutar el comando en el nodo esclavo. Porque cuando se ejecuta en el nodo maestro, bloqueará el nodo maestro;
  • Si no hay un nodo esclavo, puede optar por escanear y consultar durante el período pico bajo de la presión comercial de la instancia de Redis, para no afectar el funcionamiento normal de la instancia; o puede usar el parámetro -i para controlar el intervalo de exploración para evitar que la exploración a largo plazo reduzca el rendimiento de la instancia de Redis.

Desventajas de este método:

  • Este método solo puede devolver la clave grande más grande de cada tipo y no puede obtener la clave grande con el tamaño más grande en las N posiciones superiores;
  • Para los tipos de colección, este método solo cuenta la cantidad de elementos de la colección, no la cantidad real de memoria ocupada. Sin embargo, la gran cantidad de elementos en una colección no necesariamente ocupa una gran cantidad de memoria. Debido a que es posible que cada elemento ocupe una pequeña cantidad de memoria, en este caso, incluso si hay muchos elementos, la sobrecarga de memoria total no es grande;

2. Use el comando ESCANEAR para encontrar la llave grande

Use el comando SCAN para escanear la base de datos y luego use el comando TYPE para obtener el tipo de cada clave devuelta.

Para el tipo String, puede usar directamente el comando STRLEN para obtener la longitud de la cadena, es decir, la cantidad de bytes de espacio de memoria ocupados.

Para los tipos de colección, hay dos formas de obtener el tamaño de memoria que ocupa:

  • Si el tamaño promedio de los elementos de la colección se puede conocer de antemano desde la capa empresarial, entonces se puede usar el siguiente comando para obtener el número de elementos de la colección y luego multiplicarlo por el tamaño promedio de los elementos de la colección, de modo que el tamaño de la memoria ocupado por la colección se puede obtener. Tipo de lista: LLENcomando; Tipo de hash: HLENcomando; Tipo de conjunto: SCARDcomando; Tipo de conjunto ordenado: ZCARDcomando;
  • Si no puede saber el tamaño de los elementos escritos en la colección de antemano, puede usar MEMORY USAGEel comando (se requiere Redis 4.0 y superior) para consultar el espacio de memoria ocupado por un par clave-valor.

3. Usa la herramienta RdbTools para encontrar la clave grande

Utilice RdbTools, una herramienta de código abierto de terceros, para analizar archivos de instantáneas de Redis (RDB) y encontrar la clave principal.

Por ejemplo, el siguiente comando genera claves de más de 10 kb en un archivo de tabla.

rdb dump.rdb -c memory --bytes 10240 -f redis.csv

¿Cómo eliminar la clave grande?

La esencia de la operación de eliminación es liberar el espacio de memoria ocupado por el par clave-valor. No subestimes el proceso de liberación de memoria.

Liberar memoria es solo el primer paso. Para administrar el espacio de memoria de manera más eficiente, cuando una aplicación libera memoria, el sistema operativo necesita insertar el bloque de memoria liberada en una lista vinculada de bloques de memoria libres para su posterior administración y reasignación. El proceso en sí lleva algo de tiempo y bloquea la aplicación que actualmente está liberando memoria.

Por lo tanto, si se libera una gran cantidad de memoria a la vez, el tiempo de operación de la lista vinculada de bloque de memoria libre aumentará y, en consecuencia, se bloqueará el hilo principal de Redis. Si se bloquea el hilo principal, todas las demás solicitudes pueden agotar el tiempo de espera. , y el tiempo de espera aumentará. , hará que la conexión de Redis se agote y provocará varias excepciones.

Por lo tanto, debemos tener cuidado al eliminar una clave grande. ¿Cómo hacerlo? Aquí se dan dos métodos:

  • Eliminar en lotes
  • Eliminación asíncrona (versión Redis 4.0 y superior)

1. Eliminar en lotes

Para eliminar un Hash grande , use hscanel comando para obtener 100 campos a la vez y luego use hdelel comando para eliminar 1 campo a la vez.

código pitón:

def del_large_hash():
  r = redis.StrictRedis(host='redis-host1', port=6379)
    large_hash_key ="xxx" #要删除的大hash键名
    cursor = '0'
    while cursor != 0:
        # 使用 hscan 命令,每次获取 100 个字段
        cursor, data = r.hscan(large_hash_key, cursor=cursor, count=100)
        for item in data.items():
                # 再用 hdel 命令,每次删除1个字段
                r.hdel(large_hash_key, item[0])

Para eliminar una lista grande , elimine una pequeña cantidad de elementos cada vez que utilice ltrimel comando .

código pitón:

def del_large_list():
  r = redis.StrictRedis(host='redis-host1', port=6379)
  large_list_key = 'xxx'  #要删除的大list的键名
  while r.llen(large_list_key)>0:
      #每次只删除最右100个元素
      r.ltrim(large_list_key, 0, -101) 

Para eliminar un conjunto grande , use sscanel comando para escanear 100 elementos en el conjunto cada vez y luego use sremel comando para eliminar una clave a la vez.

código pitón:

def del_large_set():
  r = redis.StrictRedis(host='redis-host1', port=6379)
  large_set_key = 'xxx'   # 要删除的大set的键名
  cursor = '0'
  while cursor != 0:
    # 使用 sscan 命令,每次扫描集合中 100 个元素
    cursor, data = r.sscan(large_set_key, cursor=cursor, count=100)
    for item in data:
      # 再用 srem 命令每次删除一个键
      r.srem(large_size_key, item)

Para eliminar un ZSet grande , use zremrangebyrankel comando para eliminar los 100 elementos principales a la vez.

código pitón:

def del_large_sortedset():
  r = redis.StrictRedis(host='large_sortedset_key', port=6379)
  large_sortedset_key='xxx'
  while r.zcard(large_sortedset_key)>0:
    # 使用 zremrangebyrank 命令,每次删除 top 100个元素
    r.zremrangebyrank(large_sortedset_key,0,99) 

2. Eliminación asíncrona

A partir de la versión 4.0 de Redis, puede usar el método de eliminación asíncrona , usando el comando unlink en lugar de del para eliminar .

De esta forma, Redis colocará la clave en un subproceso asíncrono para su eliminación, de modo que el subproceso principal no se bloquee.

Supongo que te gusta

Origin blog.csdn.net/qq_34827674/article/details/126225192
Recomendado
Clasificación