Implementación de Redisson del principio de bloqueo distribuido
Como se muestra en la figura, el chico dibujó el principio del bloqueo distribuido de Redisson.
En pocas palabras, nos aseguramos de que nuestras claves caigan en un grupo, la operación de bloqueo sea atómica basada en un script lua y el retraso de bloqueo esté controlado por un perro guardián.
Específicamente, puede consultar blogs.com/AnXinliang/p/10019389.html
Si escribe myLock en la instancia maestra de Redis, el valor de la clave de bloqueo se copiará de forma asíncrona. a la instancia maestro-esclavo correspondiente.
Esto hará que cuando el cliente 2 intente agregar un bloqueo, completará el bloqueo en la nueva instancia maestra de Redis, mientras que el cliente 1 cree que ha agregado el bloqueo con éxito.
Esto hará que varios clientes completen el bloqueo en un bloqueo distribuido.
En este momento, el sistema inevitablemente tendrá problemas semánticos comerciales, lo que generará varios datos sucios.
Por lo tanto, este es el mayor defecto del bloqueo distribuido de Redis causado por la replicación asincrónica maestro-esclavo en el clúster de Redis o en la arquitectura maestro-esclavo de Redis: si la instancia maestra de Redis deja de funcionar, puede provocar que varios clientes se bloqueen simultáneamente. Bloqueo completo.
Si queremos garantizar una coherencia total en una arquitectura redis activa, tendremos que reescribir la lógica de bloqueo para garantizar que tanto el maestro como el esclavo deben bloquearse correctamente antes de poder bloquearse correctamente.
Podemos hacer esto en una única estructura maestro-esclavo, pero ¿qué pasa si tenemos múltiples nodos maestros relativamente independientes y ningún nodo esclavo? ¿Agregamos un servidor esclavo a uno de los servidores maestros?
Podemos hacer esto en una única estructura maestro-esclavo, pero ¿qué pasa si tenemos múltiples nodos maestros relativamente independientes y ningún nodo esclavo?
redis introduce el concepto de candado rojo: se utilizan varias instancias maestras en Redis para adquirir bloqueos, y solo la mayoría de las instancias adquieren bloqueos.
El algoritmo Redlock específico se divide en los siguientes cinco pasos:
Los pasos anteriores provienen de la explicación del bloqueo distribuido de Redis, como se muestra a continuación
"El misma clave y un valor aleatorio (el valor aleatorio se utiliza para asociar de forma única el cliente y la clave) solicita el bloqueo en N nodos"
¿Cuál es el número aleatorio aquí?
Esto es importante para evitar eliminar bloqueos creados por otros clientes. Por ejemplo, un cliente puede adquirir un candado, realizar algunas operaciones que bloquean durante más tiempo que el período de validez del candado (el momento en el que caducará la clave) y luego eliminar el candado adquirido por otro cliente. Simplemente usar DEL no es seguro porque un cliente podría eliminar el bloqueo de otro cliente. Cuando se utiliza el script anterior, cada bloqueo está "firmado" por una cadena aleatoria, por lo que el bloqueo solo se elimina si aún está establecido cuando el cliente intenta eliminarlo.
¿Cuál debería ser esta cadena aleatoria? Supongamos que son 20 bytes de /dev/urandom, pero puede encontrar formas más económicas de hacerlo lo suficientemente exclusivo para su tarea. Por ejemplo, un enfoque seguro es utilizar RC4 para inicializar /dev/urandom y luego generar una secuencia pseudoaleatoria a partir de él. Una solución más sencilla es utilizar una marca de tiempo UNIX con precisión de microsegundos y concatenar la marca de tiempo con el ID del cliente. Este método no es seguro, pero puede ser suficiente para la mayoría de los entornos.
Supongamos que **** tiene 5 nodos Redis: Supongamos que ocurren los siguientes eventos:
Para resolver este problema, introducimos el concepto de reinicio retrasado.
En otras palabras, el nodo no se reiniciará inmediatamente después del bloqueo, sino que esperará un período de tiempo mayor que el tiempo de validez del bloqueo.
De esta manera, cualquier bloqueo en el que haya participado el nodo antes del reinicio caducará y no habrá ningún impacto en los bloqueos existentes después del reinicio.
El Cliente 1 tiene una larga pausa de GC después de adquirir el bloqueo, durante la cual el bloqueo que adquirió expira mientras el Cliente 2 adquiere el bloqueo.
Cuando el cliente 1 se reanuda desde la pausa del GC, no se da cuenta de que el bloqueo que tenía ha expirado y aún emite escrituras en el recurso del que disfruta **** (como el servicio de almacenamiento) Solicitud
En este punto, el bloqueo lo mantiene el cliente 2, por lo que las solicitudes de escritura de los dos clientes pueden entrar en conflicto. (La función mutex de la cerradura está deshabilitada).
¿Cómo solucionamos este problema? Introdujimos el concepto de tokens de valla:
En primer lugar: RedLock utiliza una cadena aleatoria como token para un único servicio de bloqueo, lo que significa que para un recurso, es imposible distinguir el token de bloqueo que posee el cliente El orden en el que se adquieren las cerraduras.
El token de cercado puede entenderse como una secuencia incremental global, en lugar de una cadena aleatoria, es decir, un token ordenado, que se utiliza como token de bloqueo.
Proceso:
p>Supongamos que hay 5 nodos de Redis A, B, C, D y E.
Este problema no se puede resolver temporalmente durante la implementación de bloqueos distribuidos en Redis. Esta situación también existe en entornos de producción.
Los saltos de reloj se pueden evitar, según la infraestructura y la operación y el mantenimiento. Los saltos de reloj se pueden evitar, según la infraestructura y la operación y el mantenimiento.
Redis sigue siendo AP en lugar de CP; Si desea lograr una coherencia sólida, puede utilizar el bloqueo distribuido de Zookeeper, pero Zookeeper no está completamente exento de problemas, y el cliente y el servidor aún pueden perder la conexión.