Resumen del conocimiento de la entrevista relacionado con el aprendizaje de microservicios (Redis)


inserte la descripción de la imagen aquí

prefacio

  • ¡Este artículo se aprende de un programador de caballos oscuros, con la esperanza de brindar ayuda a los amigos que lo necesitan!

Redis conocimiento común de la entrevista

1 La diferencia entre Redis y Memcache

  • Redis admite tipos de datos más ricos (admite escenarios de aplicaciones más complejos): Redis no solo admite datos de tipo k/v simples, sino que también proporciona almacenamiento de estructuras de datos como list, set, zset y hash. Memcache admite un tipo de datos simple, String.
  • Redis admite la persistencia de datos : los datos en la memoria se pueden guardar en el disco y se pueden volver a cargar para usarlos al reiniciar, mientras que Memecache almacena todos los datos en la memoria.
  • Modo de clúster : memcached no tiene un modo de clúster nativo y necesita depender del cliente para escribir datos en fragmentos de clúster, pero Redis actualmente admite el modo de clúster de forma nativa.
  • Redis使用单线程: Memcached es un modelo de red de multiplexación de E/S sin bloqueo y de subprocesos múltiples; Redis utiliza un modelo de multiplexación de E/S de multiplexación de un solo subproceso.

2 Redis problema de subproceso único

Las principales razones por las que Redis es rápido son:

  1. completamente basado en la memoria
  2. La estructura de datos es simple, y la operación de datos también es simple
  3. Utilice el modelo de multiplexación de E/S múltiple para aprovechar al máximo los recursos de la CPU

Las ventajas del single threading son las siguientes:

  • El código es más claro y la lógica de procesamiento es más simple.
  • No hay necesidad de considerar varios problemas de bloqueo, no hay operación de liberación de bloqueo y no hay consumo de rendimiento causado por bloqueos.
  • No hay cambio de CPU causado por procesos múltiples o subprocesos múltiples, lo que hace un uso completo de los recursos de la CPU

3 esquema de persistencia de Redis

3.1 Conocimientos básicos

  1. persistencia RDB

La persistencia de RDB puede usar save o bgsave. Para no bloquear el negocio del proceso principal, generalmente se usa bgsave. El proceso:

  • El proceso de Redis bifurcará un proceso secundario (coherente con los datos de memoria del proceso principal).
  • El proceso principal continúa procesando los comandos de solicitud del cliente.
  • Escriba todos los datos en la memoria en un archivo RDB temporal por el proceso secundario.
  • Una vez completada la operación de escritura, el archivo RDB antiguo será reemplazado por el nuevo archivo RDB.

Las siguientes son algunas configuraciones relacionadas con la persistencia de RDB:

  • save 60 10000: si 10 000 claves cambian en 60 segundos, realice la persistencia de RDB.
  • stop-writes-on-bgsave-error yes: si Redis no puede realizar la persistencia de RDB (comúnmente debido a una memoria insuficiente en el sistema operativo), Redis ya no aceptará solicitudes de los clientes para escribir datos.
  • rdbcompression yes: Al generar archivos RDB, comprímalos al mismo tiempo.
  • dbfilename dump.rdb: Nombre el archivo RDB dump.rdb.
  • dir /var/lib/redis: Guarde el archivo RDB en /var/lib/redisel directorio.
  • En la práctica, generalmente stop-writes-on-bgsave-errorlo configuramos en false, y al mismo tiempo dejamos que el sistema de monitoreo envíe una alarma cuando Redis no puede realizar la persistencia de RDB, para que la intervención manual se pueda resolver en lugar de rechazar de manera grosera la solicitud de escritura del cliente.

Ventajas de la persistencia RDB:

  • Los archivos persistentes de RDB son pequeños y la recuperación de datos de Redis es rápida
  • El proceso secundario no afecta al proceso principal y el proceso principal puede continuar procesando los comandos del cliente.
  • El método copy-on-write se adopta cuando el proceso hijo está bifurcado.En la mayoría de los casos, no hay mucho consumo de memoria y la eficiencia es relativamente buena.

Desventajas de la persistencia de RDB:

  • El método de copia en escritura se adopta cuando se bifurca el proceso secundario. Si Redis escribe más en este momento, puede causar un uso de memoria adicional o incluso un desbordamiento de memoria.
  • La compresión de archivos RDB reducirá el tamaño del archivo, pero consumirá CPU adicional al pasar
  • Si el escenario empresarial valora la durabilidad de los datos (durabilidad), entonces no se debe utilizar la persistencia de RDB. Por ejemplo, si Redis ejecuta la persistencia de RDB cada 5 minutos, si Redis falla inesperadamente, perderá hasta 5 minutos de datos.

  1. persistencia AOF
  • Puede usar appendonly yeselementos de configuración para habilitar la persistencia de AOF. Cuando Redis realiza la persistencia de AOF, agregará el comando de escritura recibido al final del archivo AOF, de modo que Redis pueda restaurar la base de datos a su estado original siempre que reproduzca los comandos en el archivo AOF.
  • En comparación con la persistencia RDB, una ventaja obvia de la persistencia AOF es que puede mejorar la durabilidad de los datos. Porque en el modo AOF, cada vez que Redis recibe un comando de escritura del cliente, escribirá el comando write()al final del archivo AOF.
  • Sin embargo, en Linux, write()después de que los datos se transfieran a un archivo, los datos no se descargarán en el disco inmediatamente, sino que se almacenarán temporalmente en el búfer del sistema de archivos del sistema operativo. En el momento adecuado, el sistema operativo vaciará los datos del búfer al disco (si necesita vaciar el contenido del archivo al disco, puede llamar fsync()o fdatasync()).

A través de appendfsynclos elementos de configuración, puede controlar la frecuencia con la que Redis sincroniza los comandos con el disco:

  • always: cada vez que Redis escribe el comando write()en el archivo AOF, se llamará fsync()para vaciar el comando en el disco. Esto garantiza la mejor durabilidad de los datos, pero puede imponer una sobrecarga significativa en el sistema.
  • no: Redis solo envía comandos write()a archivos AOF. Esto permite que el sistema operativo decida cuándo vaciar los comandos en el disco.
  • everysec: además de escribir el comando write()en el archivo AOF, Redis lo ejecutará cada segundo fsync(). En la práctica, se recomienda utilizar esta configuración, que puede garantizar la persistencia de los datos hasta cierto punto sin reducir significativamente el rendimiento de Redis.

Sin embargo, la persistencia de AOF no está exenta de desventajas: Redis continuará agregando los comandos de escritura recibidos al archivo AOF, lo que hará que el archivo AOF sea cada vez más grande. Los archivos AOF grandes consumen espacio en disco y hacen que Redis se reinicie más lentamente. Para resolver este problema, en las circunstancias apropiadas, Redis reescribirá el archivo AOF para eliminar los comandos redundantes en el archivo para reducir el tamaño del archivo AOF. Durante la reescritura del archivo AOF, Redis iniciará un subproceso, y el subproceso es responsable de reescribir el archivo AOF.
  Puede controlar la frecuencia con la que Redis reescribe los archivos AOF a través de los siguientes dos elementos de configuración:

  • auto-aof-rewrite-min-size 64mb
  • auto-aof-rewrite-percentage 100

El efecto de las dos configuraciones anteriores: cuando el tamaño del archivo AOF es superior a 64 MB, y el tamaño del archivo AOF es al menos el doble del tamaño después de la última reescritura, entonces Redis realizará la reescritura AOF.

ventaja:

  • Alta frecuencia de persistencia y alta confiabilidad de datos
  • Sin memoria adicional ni consumo de CPU

defecto:

  • tamaño de archivo grande
  • Los archivos grandes conducen a una baja eficiencia en la recuperación de datos del servicio

3.2 Habilidades del habla para entrevistas

  • Redis proporciona dos métodos de persistencia de datos, uno es RDB y el otro es AOF. De forma predeterminada, Redis usa la persistencia de RDB.
  • Los archivos persistentes RDB son de tamaño pequeño, pero la frecuencia de guardado de datos es generalmente baja, la confiabilidad es baja y los datos se pierden fácilmente. Además, RDB utilizará la función Fork para copiar el proceso principal al escribir datos, lo que puede tener un consumo de memoria adicional, y la compresión de archivos también tendrá un consumo de CPU adicional.
  • La persistencia de ROF puede persistir una vez por segundo, con alta confiabilidad. Sin embargo, el archivo persistente es de gran tamaño, lo que resulta en mucho tiempo para leer el archivo durante la recuperación de datos, y la eficiencia es ligeramente baja.

4 modo de clúster de Redis

  • Los clústeres de Redis se pueden dividir en clústeres maestro-esclavo y clústeres fragmentados .
    • Los clústeres maestro-esclavo generalmente tienen un maestro y varios esclavos. La biblioteca maestra se usa para escribir datos y la biblioteca esclava se usa para leer datos. Combinado con Sentry, el maestro puede ser reelegido cuando la base de datos principal está inactiva, el propósito es garantizar la alta disponibilidad de Redis .
    • Los clústeres fragmentados son fragmentos de datos. Dejaremos que varios nodos de Redis formen un clúster y asignaremos 16383 ranuras a diferentes nodos. Al almacenar datos, use la operación hash en la clave para obtener el valor de la ranura y almacenarlo en el nodo correspondiente. Debido a que los datos de almacenamiento están orientados a la ranura en lugar del nodo en sí, el clúster se puede escalar dinámicamente. El propósito es permitir que Redis almacene más datos.

  1. clúster maestro-esclavo
    • El clúster maestro-esclavo también es un clúster de separación de lectura y escritura. Generalmente es un amo y muchos esclavos.
    • La función de replicación (replicación) de Redis permite a los usuarios crear cualquier cantidad de réplicas del servidor basadas en un servidor Redis, donde el servidor replicado es el servidor maestro (maestro) y la réplica del servidor creada por la replicación es el servidor esclavo (esclavo).
    • Siempre que la conexión de red entre los servidores maestro y esclavo sea normal, los servidores maestro y esclavo tendrán los mismos datos, y el servidor maestro siempre sincronizará las actualizaciones de datos que le suceden al servidor esclavo, asegurando así que los datos de los servidores maestro y esclavo son los mismos.
    • La escritura de datos solo se puede hacer a través del nodo maestro
    • La lectura de datos se puede hacer desde cualquier nodo.
    • Si está configurado 哨兵节点, cuando el maestro se cae, el centinela elegirá un nuevo maestro del nodo esclavo.
  • Hay dos tipos de clústeres maestro-esclavo:
    inserte la descripción de la imagen aquí
    inserte la descripción de la imagen aquí

  • Racimo con centinelas:
    inserte la descripción de la imagen aquí

  1. Clúster fragmentado
    • En el clúster maestro-esclavo, cada nodo debe guardar toda la información, lo que es fácil de formar un efecto de barril. Y cuando la cantidad de datos es grande, una sola máquina no puede satisfacer la demanda. En este momento, se utiliza un clúster fragmentado.
      inserte la descripción de la imagen aquí

Características del racimo:

  • Cada nodo contiene datos diferentes.

  • Todos los nodos redis están interconectados entre sí (mecanismo PING-PONG), utilizando internamente un protocolo binario para optimizar la velocidad de transmisión y el ancho de banda.

  • La falla de un nodo surte efecto solo cuando más de la mitad de los nodos en el clúster detectan la falla.

  • El cliente está conectado directamente al nodo redis y no se requiere una capa de proxy intermedia para conectarse a ningún nodo disponible en el clúster para acceder a los datos.

  • redis-cluster asigna todos los nodos físicos a [0-16383] slots (ranuras) para lograr escalado dinámico

Para garantizar la alta disponibilidad de cada nodo en Redis, también puede crear una replicación (nodo esclavo) para cada nodo , como se muestra en la figura:

inserte la descripción de la imagen aquí

Cuando ocurre una falla, el maestro y el esclavo pueden cambiar a tiempo :
inserte la descripción de la imagen aquí


4 tipos de datos comunes de Redis

Admite múltiples tipos de estructuras de datos, la principal diferencia es que el formato de datos del almacenamiento de valor es diferente:

  • cadena: El tipo de datos más básico, una cadena binaria segura, hasta 512M.

  • lista: una lista de cadenas que mantienen el orden en el orden en que se agregaron.

  • conjunto: una colección desordenada de cadenas sin elementos duplicados.

  • conjunto ordenado: una colección ordenada de cadenas.

  • hash: formato de par clave-valor


5 mecanismo de transacción de Redis

La función de transacción de Redis se realiza a través de las cuatro primitivas de MULTI, EXEC, DISCARD y WATCH. Redis serializa todos los comandos en una transacción y los ejecuta secuencialmente. Sin embargo, las transacciones de Redis no admiten operaciones de reversión.Después de que un comando se ejecuta incorrectamente, el comando correcto continuará ejecutándose.

  • MULTI: Se utiliza para iniciar una transacción, siempre devuelve OK. Después de ejecutar MULTI, el cliente puede continuar enviando cualquier cantidad de comandos al servidor. Estos comandos no se ejecutarán inmediatamente, sino que se colocarán en una cola de comandos para ser ejecutados.
  • EXEC: Ejecuta todos los comandos en la cola de comandos secuencialmente. Devuelve el valor de retorno de todos los comandos. Durante la ejecución de la transacción, Redis no ejecutará comandos de otras transacciones.
  • DISCARD: borre la cola de comandos y abandone la ejecución de la transacción, y el cliente saldrá del estado de transacción
  • WATCH: El mecanismo de bloqueo optimista de Redis, que utiliza el principio de comparar y configurar (CAS), puede monitorear una o más claves. Una vez que se modifica una de las claves, las transacciones posteriores no se ejecutarán.

Al usar transacciones, puede encontrar los siguientes dos tipos de errores:

  • Los comandos en cola pueden dañarse antes de que se ejecute EXEC. Por ejemplo, un comando puede producir un error de sintaxis (número incorrecto de argumentos, nombre de argumento incorrecto, etc.) u otros errores más graves, como memoria insuficiente (si el servidor usa un límite máximo de memoria maxmemoryestablecido
    • A partir de Redis 2.6.5, el servidor registrará la falla al poner en cola el comando, y cuando el cliente llame al comando EXEC, se negará a ejecutar y abandonará automáticamente la transacción.
  • El comando puede fallar después de la llamada EXEC. Por ejemplo, un comando en una transacción puede manejar el tipo de clave incorrecto, como usar un comando de lista en una clave de cadena, etc.
    • Incluso si algunos/algunos comandos en la transacción generan un error durante la ejecución, otros comandos en la transacción seguirán ejecutándose y no se revertirán.

¿Por qué Redis no admite la reversión (roll back)? Estas son las ventajas de este enfoque:

  • Los comandos de Redis solo pueden fallar debido a una sintaxis incorrecta (y estos problemas no se pueden detectar al poner en cola), o porque el comando se usa en el tipo de clave incorrecto: es decir, desde un punto de vista práctico, el comando que falla es causado por errores de programación , y estos errores deben encontrarse en el proceso de desarrollo, y no deben aparecer en el entorno de producción.
  • Dado que no hay necesidad de admitir reversiones, las funciones internas de Redis pueden mantenerse simples y rápidas.

Dado que no existe un mecanismo para evitar los errores causados ​​por los propios programadores, y dichos errores generalmente no aparecen en un entorno de producción, Redis elige una forma más simple y rápida de manejar las transacciones sin retroceder.


  • Discurso de la entrevista:
    • Las transacciones de Redis en realidad colocan una serie de comandos de Redis en la cola y luego los ejecutan en lotes sin interrupción por otras transacciones durante la ejecución. Sin embargo, a diferencia de las transacciones de bases de datos relacionales, las transacciones de Redis no admiten operaciones de reversión.Si un comando no se ejecuta en una transacción, se seguirán ejecutando otros comandos. Para compensar el problema de no poder retroceder, Redis verificará el comando cuando la transacción esté en cola y, si el comando es anormal, se abandonará toda la transacción. Por lo tanto, siempre que la programación del programador sea correcta, en teoría, Redis ejecutará todas las transacciones correctamente sin retroceder.

  • Qué hacer si Redis falla en medio de la ejecución de una transacción

  • Redis tiene un mecanismo de persistencia. Debido a problemas de confiabilidad, generalmente usamos la persistencia AOF. Todos los comandos de la transacción también se escribirán en el archivo AOF, pero si Redis está inactivo antes de que se ejecute el comando EXEC, la transacción en el archivo AOF estará incompleta. Utilice redis-check-aofel programa para eliminar la información de transacción incompleta en el archivo AOF para asegurarse de que el servidor pueda iniciarse sin problemas.


6 Política de caducidad de claves de Redis

  1. ¿Por qué necesita recuperación de memoria?
    1. En Redis, el comando set puede especificar el tiempo de vencimiento de la clave. Cuando se alcanza el tiempo de vencimiento, la clave dejará de ser válida;
    2. Redis se basa en operaciones de memoria, todos los datos se almacenan en la memoria y la memoria de una máquina es limitada y muy valiosa.
      Con base en los dos puntos anteriores, para garantizar que Redis pueda continuar brindando servicios confiables, Redis necesita un mecanismo para limpiar los datos redundantes, inválidos y de uso poco frecuente. Los datos no válidos deben limpiarse a tiempo, lo que requiere memoria. reciclaje.
  • La recuperación de memoria de Redis se divide principalmente en dos partes: estrategia de eliminación caducada y estrategia de eliminación de memoria.

6.1 Política de eliminación vencida

  • Elimine las claves que hayan llegado a su fecha de caducidad.
  1. Eliminación programada

    • Se creará un temporizador para cada clave con un tiempo de caducidad establecido, y se eliminará inmediatamente una vez que se alcance el tiempo de caducidad. Esta estrategia puede borrar inmediatamente los datos caducados, lo que es más amigable con la memoria, pero la desventaja es que consume muchos recursos de la CPU para procesar los datos caducados, lo que afectará el rendimiento y el tiempo de respuesta de Redis.
  2. borrado perezoso

    • Cuando se accede a una clave, se juzga si la clave caduca y se elimina cuando caduca. Esta estrategia puede ahorrar recursos de CPU en la mayor medida, pero es muy poco amigable para la memoria. En un caso extremo, es posible que no se vuelva a acceder a una gran cantidad de claves caducadas, por lo que no se borrarán, lo que generará una gran cantidad de memoria.

En informática, la eliminación perezosa (en inglés: lazy deletion) se refiere a un método para eliminar elementos de una tabla hash (también conocida como tabla hash). En este método, la eliminación solo se refiere a marcar un elemento para eliminarlo, en lugar de borrarlo por completo. Las posiciones eliminadas se tratan como elementos vacíos cuando se insertan y se ocupan cuando se buscan.

  1. eliminar regularmente
    • De vez en cuando, escanee el diccionario de claves caducadas en Redis y borre algunas claves caducadas. Esta estrategia es un compromiso entre las dos anteriores. También puede lograr el equilibrio óptimo de recursos de CPU y memoria en diferentes circunstancias ajustando el intervalo de tiempo de los análisis programados y el consumo de tiempo limitado de cada análisis.
  • En Redis, 同时使用了定期删除和惰性删除. Sin embargo, Redis elimina regularmente algunas claves mediante selección aleatoria, por lo que no puede garantizar la eliminación del 100 % de las claves caducadas. Redis combina la eliminación regular y la eliminación perezosa, y básicamente puede manejar muy bien la limpieza de datos caducados, pero de hecho todavía hay algunos problemas.Si hay muchas claves caducadas, algunas de ellas se pierden con la eliminación regular y no se verifican. con el tiempo, es decir, si no hay una eliminación perezosa, se acumulará una gran cantidad de claves caducadas en la memoria, lo que provocará el agotamiento de la memoria redis. Cuando se agote la memoria, ¿qué sucederá cuando lleguen nuevas claves? ¿Hay alguna forma de aceptar más claves?

6.2 Estrategia de eliminación de memoria

  • La estrategia de eliminación de memoria de Redis significa que cuando la memoria alcanza el límite máximo de memoria, se usa un algoritmo para determinar qué datos limpiar para garantizar el almacenamiento de nuevos datos.

El mecanismo de eliminación de memoria de Redis incluye:

  • noeviction: cuando la memoria no es suficiente para acomodar los datos recién escritos, la nueva operación de escritura informará un error.
  • allkeys-lru: cuando la memoria no es suficiente para acomodar los datos recién escritos, en el espacio de claves ( server.db[i].dict), elimine la clave utilizada menos recientemente (esta es la más utilizada).
  • allkeys-random: cuando la memoria no es suficiente para acomodar los datos recién escritos, en el espacio de claves ( server.db[i].dict), elimine una clave al azar.
  • volatile-lru: cuando la memoria no es suficiente para acomodar los datos recién escritos, en el espacio de claves ( server.db[i].expires) con el tiempo de caducidad establecido, elimine la clave utilizada menos recientemente.
  • server.db[i].expiresvolátil-aleatorio: cuando la memoria no es suficiente para acomodar los datos recién escritos, se elimina aleatoriamente una clave del espacio de claves ( ) con el tiempo de caducidad establecido .
  • volatile-ttl: cuando la memoria no es suficiente para acomodar los datos recién escritos, en el espacio de claves ( ) con el tiempo de vencimiento establecido server.db[i].expires, la clave con el tiempo de vencimiento anterior se elimina primero.

En el archivo de configuración, qué mecanismo de eliminación usar se puede configurar a través de maxmemory-policy.

  • ¿Cuándo tendrá lugar la eliminación?
    • Redis juzgará si el redis actual ha alcanzado el límite máximo de memoria cada vez que procesa un comando (la función processCommand llama a freeMemoryIfNeeded).Si alcanza el límite, utilizará el algoritmo correspondiente para procesar la clave que debe eliminarse.

    • Al eliminar claves, Redis utiliza de forma predeterminada el algoritmo LRU más utilizado (Último utilizado recientemente). Redis guarda el último tiempo de acceso de la clave guardando el atributo lru en cada redisObject y lee directamente el atributo lru de la clave al implementar el algoritmo LRU.

En la implementación específica, Redis atraviesa cada base de datos, selecciona aleatoriamente un lote de claves de muestra de cada base de datos, el valor predeterminado es 3 claves y luego elimina la clave utilizada menos recientemente de estas 3 claves.

6.3 Habilidades de discurso de entrevista:

La estrategia de caducidad de Redis incluye dos partes: eliminación regular y eliminación diferida. La eliminación periódica es una tarea programada dentro de Redis, que eliminará periódicamente algunas claves caducadas. La eliminación diferida significa que cuando un usuario consulta una clave, verificará si la clave ha caducado, se la devolverá al usuario si no ha caducado y la eliminará si caduca.

Sin embargo, ninguna de estas dos estrategias puede garantizar que la clave caducada se elimine y que más y más peces se escapen de la red, lo que también puede provocar un desbordamiento de la memoria. Cuando ocurre un problema de falta de memoria, Redis también realizará la recuperación de la memoria. La recuperación de memoria adopta la estrategia LRU, que es la menos utilizada recientemente. El principio es registrar el tiempo de uso más reciente de cada clave y, cuando se recupera la memoria, seleccionar aleatoriamente algunas claves, comparar su tiempo de uso y eliminar las más antiguas.

La lógica de Redis es: lo que se ha usado recientemente es probable que se vuelva a usar

7 El papel de Redis en el proyecto

  1. sesión compartida

En un sistema distribuido, los servicios se implementarán en diferentes tomcats, por lo que no se pueden compartir múltiples sesiones de tomcat, y los datos almacenados en sesiones no se pueden compartir antes.Se puede usar Redis en lugar de sesiones para resolver el problema de compartir datos entre sistemas distribuidos.

  1. caché de datos

Redis utiliza almacenamiento en memoria, que tiene una alta eficiencia de lectura y escritura. Podemos almacenar datos calientes con alta frecuencia de acceso a la base de datos en redis, para que los usuarios puedan leer desde redis primero cuando lo soliciten, reduciendo la presión de la base de datos y mejorando la concurrencia.

  1. cola asíncrona

Una de las principales ventajas de Reids en el campo de los motores de almacenamiento de memoria es que proporciona operaciones de lista y configuración, lo que convierte a Redis en una buena plataforma de colas de mensajes para usar. Además, también hay una estructura dedicada como pub/sub en Redis, que se utiliza para el modo de comunicación de mensajes 1 a N.

  1. bloqueo distribuido

El mecanismo de bloqueo optimista en Redis puede ayudarnos a lograr el efecto de bloqueos distribuidos y resolver problemas de seguridad de subprocesos múltiples en sistemas distribuidos.

8 Desglose de caché de Redis, avalancha de caché, penetración de caché

8.1 Penetración de caché

Referencias:

  • ¿Qué es la penetración de caché?

    • En circunstancias normales, cuando consultamos datos, existen. Luego solicite consultar un dato que no existe en absoluto en la base de datos, es decir, ni el caché ni la base de datos pueden consultar estos datos, pero la solicitud llegará a la base de datos cada vez. Este fenómeno de consultar datos que no existen se denomina penetración de caché .
  • problemas con la penetración

    • Imagínese, si un pirata informático ataca su sistema y usa una identificación inexistente para consultar datos, se generará una gran cantidad de solicitudes a la base de datos para la consulta. Puede hacer que su base de datos se bloquee debido a una presión excesiva.
  • Solución

    • Caché de valores vacíos: la razón por la que se produce la penetración es que no existe una clave para almacenar estos datos vacíos en la caché. Como resultado, cada consulta va a la base de datos. Luego podemos establecer los valores correspondientes a estas claves en nulo y tirarlos al caché. Cuando haya una solicitud para consultar esta clave más adelante, se devolverá un valor nulo directamente. De esta manera, no tiene que dar vueltas por la base de datos, pero no olvide establecer el tiempo de caducidad.
    • BloomFilter (filtro Bloom): haga un hash de todos los datos posibles en un mapa de bits lo suficientemente grande, y los datos que no deben existir serán interceptados por este mapa de bits, evitando así la presión de consulta en el sistema de almacenamiento subyacente. Agregue una capa de BloomFilter antes del caché. Al consultar, primero vaya al BloomFilter para verificar si la clave existe. Si no existe, devuélvala directamente. Si existe, verifique el caché -> verifique la base de datos.

Palabras:

Hay dos soluciones para la penetración de la memoria caché: una es establecer un valor nulo en la memoria caché para una clave que no existe. El segundo es usar el filtro Bloom.Antes de consultar el caché, el filtro Bloom se usa para determinar si la clave existe y luego consultar el caché.

Establecer un valor nulo puede tener un objetivo malicioso y el atacante usa una gran cantidad de claves únicas inexistentes, entonces la Solución 1 almacenará en caché una gran cantidad de datos clave inexistentes. En este momento, también podemos especificar una plantilla de formato para la clave y luego realizar una comparación regular de especificaciones para la clave inexistente . Si no coincide en absoluto, no es necesario almacenar el valor nulo en redis, sino directamente devuelve un error.


8.2 Desglose de caché

  • ¿Qué es el desglose de caché?

Se puede acceder a la clave en un momento determinado con alta simultaneidad, que es un dato muy "caliente". En este momento, se debe considerar un problema: el problema de que el caché se "descompone".

Cuando la clave caduca en ese momento, la consulta redis falla y la gran simultaneidad continua atravesará el caché y solicitará directamente la base de datos, como si cavara un agujero en una barrera.

  • solución:
    • Use mutex (clave mutex): mutex es exclusión mutua. En pocas palabras, cuando la memoria caché falla (considerando que el valor extraído está vacío), en lugar de cargar db inmediatamente, primero use SETNX de Redis para establecer una clave de exclusión mutua y luego cargue cuando la operación regrese con éxito. caché; de lo contrario, vuelva a intentar todo el método de obtención de caché. SETNX es la abreviatura de "SET if Not eXists", es decir, solo se establece cuando no existe, y se puede utilizar para lograr la exclusión mutua.
    • Caducidad suave: es decir, caducidad lógica, en lugar de utilizar el tiempo de caducidad proporcionado por redis, la capa empresarial almacena información de tiempo de caducidad en los datos. Al consultar, el programa comercial juzga si está caducado. Si los datos están a punto de caducar, el límite de tiempo del caché se extenderá. El programa puede enviar un hilo a la base de datos para obtener los datos más recientes. Otros hilos continuarán utilícelo cuando vean el tiempo de caducidad extendido Para los datos antiguos, espere a que el subproceso enviado obtenga los datos más recientes antes de actualizar el caché.

Se recomienda utilizar una exclusión mutua, porque la expiración suave tendrá una intrusión de lógica comercial y un juicio adicional.

Discurso de la entrevista :

La principal preocupación de la avería de la memoria caché es que una clave caduca, lo que provoca un acceso simultáneo elevado y repentino a la base de datos cuando se actualiza la memoria caché. Por lo tanto, podemos usar el control mutex al actualizar el caché, permitiendo que solo un subproceso actualice el caché, mientras que otros subprocesos esperan y vuelven a leer el caché. Por ejemplo, el comando setnx de Redis puede lograr la exclusión mutua.

8.3 Avalancha de caché

Información relacionada :

Avalancha de caché significa que dentro de un cierto período de tiempo, el conjunto de caché caduca y deja de ser válido. La consulta de acceso para este lote de datos recae en la base de datos y, para la base de datos, habrá picos de presión periódicos.

solución:

  • Clasificación de datos y procesamiento por lotes: tome diferentes datos de clasificación y almacene en caché diferentes ciclos
  • Datos de la misma categoría: configura el caché con una duración fija y un número aleatorio
  • El tiempo de caché de los datos calientes es más largo y el tiempo de caché de los datos impopulares es más corto
  • Evite las avalanchas causadas por el tiempo de inactividad del nodo Redis, cree clústeres maestro-esclavo y garantice una alta disponibilidad

Discurso de la entrevista:

La clave para resolver el problema de la avalancha de caché es dispersar el tiempo de caducidad de las claves de caché. Por lo tanto, podemos clasificar los datos según el negocio y luego establecer diferentes tiempos de vencimiento. Para claves del mismo tipo de negocio, establezca una duración fija más un número aleatorio. Intente asegurarse de que el tiempo de caducidad de cada clave sea diferente.

Además, el tiempo de inactividad de Redis también puede causar una avalancha de caché, por lo que debemos crear un clúster maestro-esclavo de Redis y un monitoreo centinela para garantizar la alta disponibilidad de Redis.

9 Separación de datos calientes y fríos de caché

Información de fondo :

Redis usa almacenamiento de memoria y, cuando se requiere un almacenamiento de datos masivo, el costo es muy alto.

Después de la investigación, se encontró que la brecha de precio de costo unitario entre la memoria DDR3 convencional y la SSD SATA convencional es de aproximadamente 20 veces.Para optimizar el costo general de las máquinas redis, consideramos implementar almacenamiento de datos jerárquico basado en estadísticas de calor y dinámica de datos entre Intercambio RAM / FLASH, reduciendo considerablemente los costes y consiguiendo un alto equilibrio entre rendimiento y coste.

Idea básica: los datos calientes se identifican según el algoritmo de estadísticas de calor de los tiempos de acceso clave (LFU), y los datos calientes se mantienen en redis, y los datos sin acceso/menos tiempos de acceso se transfieren al SSD. el SSD se redistribuye se calienta, se vuelve a cargar en la memoria redis.

Las soluciones de almacenamiento en disco de alto rendimiento actualmente populares que siguen el protocolo Redis incluyen:

  • SSDB

  • RocasDB

  • Por lo tanto, debemos introducir un proxy entre la aplicación y el servicio de caché para cambiar entre Redis y SSD, como se muestra en la figura:
    inserte la descripción de la imagen aquí


10 Redis implementa bloqueos distribuidos

Condiciones que deben cumplir los bloqueos distribuidos:

  • Exclusión mutua multiproceso: al mismo tiempo, solo un proceso puede adquirir el bloqueo
  • Garantizar que el bloqueo pueda liberarse: cuando la tarea finaliza o se produce una excepción, el bloqueo debe liberarse para evitar un punto muerto
  • Bloqueo de bloqueo (opcional): si se debe volver a intentar cuando falla la adquisición de un bloqueo
  • Bloqueo reentrante (opcional): cuando el código para adquirir el bloqueo se llama recursivamente, el bloqueo aún se puede adquirir

10.1 El bloqueo distribuido más básico:

  • Usando el comando setnx de Redis, si este comando se ejecuta varias veces, solo la primera ejecución tendrá éxito y se 互斥puede lograr el efecto. Sin embargo, para garantizar que el bloqueo se pueda liberar cuando el servicio está inactivo, debe usar el comando expire para establecer un período de validez para el bloqueo.

    setnx lock thread-01 # 尝试获取锁
    expire lock 10 # 设置有效期
    
  • Pregunta del entrevistador 1 : ¿Qué sucede si el servicio se cae antes de que caduque?

    • Para garantizar la atomicidad de los comandos setnx y expire. El comando set de redis puede satisfacer:
    set key value [NX] [EX time] 
    
    • Necesita agregar opciones para nx y ex:
      • NX: consistente con setnx, ejecución exitosa por primera vez
    • EX: establecer el tiempo de caducidad
  • Pregunta del entrevistador 2 : Al liberar el candado, si su propio candado ha caducado, habrá un agujero de seguridad en este momento, ¿cómo solucionarlo?

    • Almacene el proceso actual y la identificación del subproceso en el bloqueo, juzgue la identificación del bloqueo cuando libere el bloqueo, elimínelo si es suyo y abandone la operación si no lo es. Sin embargo, para garantizar la atomicidad de estos dos pasos, debe implementarse a través de scripts de Lua.
    if redis.call("get",KEYS[1]) == ARGV[1] then
        redis.call("del",KEYS[1])
    end
    

10.2 Bloqueos distribuidos reentrantes

Si hay necesidad de reingreso, además de registrar el ID del proceso en la cerradura, también se debe registrar el número de reintentos, el proceso es el siguiente:

inserte la descripción de la imagen aquí

  • Supongamos que la clave de la cerradura es " lock", hashKey es la identificación del hilo actual: " threadId", y se supone que el tiempo de liberación automática de la cerradura es 20

Pasos para adquirir un candado:

  • 1. Determinar si existe el bloqueoEXISTS lock
    • Existe, lo que indica que alguien ha adquirido el candado. A continuación, juzgue si es su propio candado.
      • Determine si la identificación del hilo actual existe como hashKey:HEXISTS lock threadId
        • Si no existe, significa que el bloqueo ya existe y no se obtiene por sí mismo.La adquisición del bloqueo falla, fin
        • Existe, indicando que es un bloqueo adquirido por sí mismo, y el número de reingresos +1: HINCRBY lock threadId 1, vaya al paso 3
    • 2. No existe, indicando que se puede adquirir el candado.HSET key threadId 1
    • 3. Configure el tiempo de liberación automática de bloqueo,EXPIRE lock 20

Pasos para liberar el candado:

  • 1. Determine si la identificación del subproceso actual existe como hashKey:HEXISTS lock threadId
    • Si no existe, significa que el bloqueo ha caducado, así que no te preocupes.
    • Existe, indicando que la cerradura sigue ahí, y se reduce en 1 el número de reingresos: HINCRBY lock threadId -1, para obtener un nuevo número de reingresos
  • 2. Determinar si el número de reingresos es 0:
    • Si es 0, significa que se liberan todos los bloqueos y se elimina la clave:DEL lock
    • Si es mayor que 0, significa que el bloqueo aún está en uso y el tiempo válido se restablece:EXPIRE lock 20

El script Lua correspondiente es el siguiente:

Lo primero es adquirir el candado:

local key = KEYS[1]; -- 锁的key
local threadId = ARGV[1]; -- 线程唯一标识
local releaseTime = ARGV[2]; -- 锁的自动释放时间

if(redis.call('exists', key) == 0) then -- 判断是否存在
	redis.call('hset', key, threadId, '1'); -- 不存在, 获取锁
	redis.call('expire', key, releaseTime); -- 设置有效期
	return 1; -- 返回结果
end;

if(redis.call('hexists', key, threadId) == 1) then -- 锁已经存在,判断threadId是否是自己	
	redis.call('hincrby', key, threadId, '1'); -- 不存在, 获取锁,重入次数+1
	redis.call('expire', key, releaseTime); -- 设置有效期
	return 1; -- 返回结果
end;
return 0; -- 代码走到这里,说明获取锁的不是自己,获取锁失败

Luego suelte el candado:

local key = KEYS[1]; -- 锁的key
local threadId = ARGV[1]; -- 线程唯一标识
local releaseTime = ARGV[2]; -- 锁的自动释放时间

if (redis.call('HEXISTS', key, threadId) == 0) then -- 判断当前锁是否还是被自己持有
    return nil; -- 如果已经不是自己,则直接返回
end;
local count = redis.call('HINCRBY', key, threadId, -1); -- 是自己的锁,则重入次数-1

if (count > 0) then -- 判断是否重入次数是否已经为0
    redis.call('EXPIRE', key, releaseTime); -- 大于0说明不能释放锁,重置有效期然后返回
    return nil;
else
    redis.call('DEL', key); -- 等于0说明可以释放锁,直接删除
    return nil;
end;

10.3 Bloqueos de alta disponibilidad

面试官问题: El bloqueo distribuido de Redis depende de Redis, si Redis falla, el bloqueo fallará. ¿Cómo resolver?

En este momento, la mayoría de los estudiantes responderán: construir un clúster maestro-esclavo y hacer una copia de seguridad de los datos.

Así es como se cae en la trampa, porque llega la siguiente pregunta del entrevistador:

面试官问题: Si al crear un clúster maestro-esclavo para la copia de seguridad de datos, el proceso A adquiere el bloqueo, pero el maestro no ha hecho una copia de seguridad de los datos en el esclavo, el maestro está inactivo y el esclavo se actualiza a maestro. el bloqueo original deja de ser válido y otros procesos también pueden adquirir el bloqueo, lo que genera un problema de seguridad. ¿Cómo resolver?

Con respecto a este problema, el sitio web oficial de Redis brinda una solución, que se puede resolver utilizando la idea de RedLock:

En el entorno distribuido de Redis, asumimos que hay N maestros de Redis. Estos nodos son completamente independientes entre sí y no hay replicación maestro-esclavo u otros mecanismos de coordinación de clústeres. Anteriormente describimos cómo adquirir y liberar bloqueos de manera segura en una sola instancia de Redis. Nos aseguramos de que los bloqueos se adquieran y liberen utilizando este método en cada (N) instancias. En este ejemplo, asumimos que hay 5 nodos maestros de Redis, lo cual es una configuración razonable, por lo que necesitamos ejecutar estas instancias en 5 máquinas o 5 máquinas virtuales, para asegurarnos de que no se caigan todas al mismo tiempo. .

Para adquirir el candado, el cliente deberá hacer lo siguiente:

  1. Obtenga la hora actual de Unix en milisegundos.
  2. Intenta adquirir bloqueos de N instancias en secuencia, usando la misma clave y valor aleatorio. En el paso 2, al establecer el bloqueo en Redis, el cliente debe configurar una conexión de red y un tiempo de espera de respuesta, que debe ser inferior al tiempo de caducidad del bloqueo. Por ejemplo, si su bloqueo caduca automáticamente en 10 segundos, el tiempo de espera debe ser de 5 a 50 milisegundos. Esto puede evitar la situación en la que Redis del lado del servidor se ha colgado y el cliente sigue esperando el resultado de la respuesta. Si el servidor no responde dentro del tiempo especificado, el cliente debe probar con otra instancia de Redis lo antes posible.
  3. El cliente utiliza la hora actual para restar la hora de inicio de adquirir el bloqueo (la hora registrada en el paso 1) para obtener el tiempo utilizado para adquirir el bloqueo. Si y solo si el bloqueo se obtiene de la mayoría de los nodos de Redis (aquí 3 nodos), y el tiempo utilizado es menor que el tiempo de vencimiento del bloqueo, el bloqueo se considera exitoso.
  4. Si se obtiene el bloqueo, el tiempo efectivo real de la llave es igual al tiempo efectivo menos el tiempo empleado para adquirir el bloqueo (resultado calculado en el paso 3).
  5. Si por alguna razón, la adquisición del bloqueo falla (el bloqueo no se adquiere en al menos N/2+1 instancias de Redis o el tiempo de adquisición del bloqueo ha excedido el tiempo efectivo), el cliente debe desbloquear todas las instancias de Redis (incluso si algunas instancias de Redis instancia no está bloqueada con éxito en absoluto).

11 Hacer que la base de datos sea coherente con los datos almacenados en caché

Las opciones de implementación son las siguientes:

  • Sincronización de caché local: los datos de la base de datos del microservicio actual se sincronizan con los datos de la caché, y la lógica de modificación para Redis se puede agregar directamente cuando se modifica la base de datos para garantizar la coherencia.
  • Sincronización de caché entre servicios: el servicio A llama al servicio B y almacena en caché los resultados de la consulta. Modificación de la base de datos del servicio B, el servicio A se puede notificar a través de MQ y el servicio A modifica los datos de caché de Redis
  • Solución general: use el marco de Canal, simule ser el nodo de salvación de MySQL, controle los cambios de binLog de MySQL y luego modifique los datos de caché de Redis

Supongo que te gusta

Origin blog.csdn.net/yang2330648064/article/details/130320591
Recomendado
Clasificación