Distribuido de bloqueo: para lograr redis de un solo nodo

En primer lugar, la concurrencia entre los hilos

Si queremos ejecutar dos hilos sincronizan, sólo se necesita agregar sychronzied o utilizar la clase Reetrantlock para garantizar la aplicación de múltiples hilos dentro del mismo proceso de sincronización JVM.

Así que si este sistema se distribuye, por ejemplo: de rosca en ambos servidores que ejecutan concurrentemente falta a la forma de hacerlo?

Y nosotros queremos lograr es que este sub-sub-caída:

De hecho, el más importante es el funcionamiento de la cerradura, obtener y liberar los bloqueos.

Dos, Redis lograr

1, la cerradura

set(key,线程的id,30,NX)

El bloqueo se consigue mediante la colocación de los datos en una redis, esta métodos set: Si la corriente no es REDIS esta clave, devuelve 1 si se devuelve 0. De esta manera se puede. set manera de concurrencia entre los diferentes hilos de control, sólo la aplicación de este método devuelve 1 cuando se considere adquirir el bloqueo.

Los últimos dos parámetros se ajustan el tiempo de caducidad. Si no se establece lo que sucede? Por ejemplo, el hilo A adquiere el bloqueo, entonces el programa no murió, el bloqueo no se ha sido puesto en libertad, los otros hilos del servidor no conseguirán la cerradura. Por lo tanto, establecer una fecha de caducidad de significación: Después de llegar a la fecha de caducidad, a continuación, los datos se cancela automáticamente (por supuesto, desea establecer una buena ReDiS memoria mecanismo de eliminación), que es la liberación de la cerradura, no afecta el otro hilo puede obtener el conjunto de bloqueo .

Algunos dicen que :( ¿Puede lograrse son los siguientes pseudo-código)

setnx(key,1)
expire(key,30)

Redis utilizan estos dos comandos para lograr: la respuesta es NO

Debemos asegurarnos de que el proceso es un encerrados operaciones atómicas , por ejemplo, el extremo del hilo de un cliente después de ejecutar setnx después (clave 1) está muerto, la cerradura todavía no se adquiere por otro subproceso.

2, el bloqueo se libera

Un hilo se ejecuta después de la finalización de los bloques de código de sincronización, de bloqueo lleva a cabo se libera

del(key)

Este método está bien? NO, NO, NO. Por supuesto que no

Considere esto: Si la fecha de vencimiento está establecido actualmente por 30 segundos, a continuación, después de que el subproceso de ejecución Un encerrarse en el bloque de código de sincronización de contenido, después de 30 segundos, Redis vieron al tiempo, poner la llave retirada, el bloqueo se libera, y esta vez no se ha ejecutado todavía un acabado, por lo que el hilo Bset un poco y encontró que se puede obtener el bloqueo, hilo B en un juego agradable, pero esta vez enhebrar una ejecutado más (no ReDiS cuenta que libera el bloqueo ), este hombre pensó que seguía bloquearla, luego soltarlo, esta vez, el hilo de bloqueo B también se ha eliminado, la clave es que este hombre no conoce el bloqueo se elimina. De esta manera hay un problema de concurrencia. Como ser cornudo no sé la misma.

Podemos establecer conjunto de valores almacenados para el ID del tema (pensamientos personales son: + ID identifica de forma exclusiva el hilo del servidor = valor)

加锁:
String threadId = Thread.currentThread().getId()
set(key,threadId ,30,NX)

解锁:
if(threadId .equals(redisClient.get(key))){
del(key)
}

Pero parecía un problema, liberación del bloqueo no es una operación atómica. Confío en que habrá problemas ah.

Echemos un vistazo a un escenario como este:

O el caso del ejemplo anterior, después de que el juez de rosca acabada A no es el ID del tema actual, entonces el momento clave expiró. B hilo quedó encerrado, y luego realiza una todavía aparecía en el caso anterior.

Debemos reemplazar del, el uso de la escritura para lograr lua, la hebilla 1.

String luaScript = "if redis.call('get', KEYS[1]) == ARGV[1] 
then return redis.call('del', KEYS[1]) else return 0 end";

redisClient.eval(luaScript , Collections.singletonList(key), Collections.singletonList(threadId));

Una pequeña socios tienen que decir, después de discussion A venza primero, aún en marcha, hilo B se ejecuta para adquirir el bloqueo, que no se ajusta a las normas ah. Aquí tenemos que resolver este problema.

Podemos establecer un cuchillo guardias de rosca, como JR guardia de LeBron James (algo hace unos años). Para unos guardias imperiales, en Java, es el guardián de la rosca! Por supuesto, usted tiene que saber lo que es el guardián de la rosca.

Este hilo de utilidad es sólo un papel,

Cuando han transcurrido los 29 segundos, el hilo A no se ha realizado, este hilo de utilidad tiempo ejecutará expirará instrucciones de la cerradura "continuó la vida" durante 20 segundos. hilo de utilidad se inicia la ejecución de 29 segundos para ejecutar una vez cada 20 segundos.

 

Cuando hilo A ejecutado, este hilo daemon habrá terminado.

Publicados 134 artículos originales · ganado elogios 91 · vistas 160 000 +

Supongo que te gusta

Origin blog.csdn.net/weixin_44588495/article/details/104563365
Recomendado
Clasificación