php + + Redis lua lograr Distributed Lock (reimpresión)

Aquí está lo que yo uso en la clase de trabajo, Redis encerrado en dos formas, con el fin de garantizar la atomicidad desbloqueado por lo que sólo lua + ReDiS camino

Defectos: Mientras se resuelve punto muerto, pero el período de tiempo de ejecución de negocios o hay más de cuestiones de bloqueo multi-cliente de bloqueo.
Sin embargo, esta clase ha cumplido con mis necesidades de negocio actuales

Mejores soluciones pueden hacer referencia a los dos artículos siguientes:
https://redis.io/topics/distlock (descripción algorítmica de Redlock)
https://mp.weixin.qq.com/s/1bPLk_VZhZ0QYNZS8LkviA

la implementación del código:

RedisLock clase
{
/ **
* @ var identificación de bloqueo actual, para el desbloqueo
* /
privada $ _lockFlag;

$ _redis privadas;

__construct función pública ($ host = '127.0.0.1', $ port = '6379', $ passwd = '')
{
$ this -> _ Redis = new Redis ();
$ this -> _ redescubrir> connect ($ host, $ puerto);
if ($ passwd) {
$ this -> _ redescubrir> auth ($ passwd);
}
}

bloqueo de la función pública ($ clave, expiran $ = 5)
{
$ ahora = time ();
$ ExpireTime = $ $ + expira ahora;
if ($ this -> _ redescubrir> setnx ($ clave, $ ExpireTime)) {
$ this -> _ lockFlag = $ ExpireTime;
return true;
}

// obtener un bloqueo en el tiempo de expiración
$ = $ currentLockTime la this -> _ redescubrir> get ($ key);
SI (currentLockTime $ <$ ahora) {
/ * Solución
C0 tiempo extra, también se mantiene el bloqueo, se añadió C1 / C2 / ... método dentro de solicitudes simultáneas en
C1 / C2 GetSet realizar un proceso (proceso porque GetSet atómico,
por lo que el valor de dos solicitud vuelto desigual debe asegurar que el C1 / C2 sólo adquieren una cerradura) * /
$ $ = oldLockTime la this -> _ redescubrir> GetSet (clave $, $ ExpireTime);
SI (== $ $ currentLockTime oldLockTime) {
-;> _ lockFlag = $ $ ExpireTime el presente
; el retorno a la verdadera
}
}

falso retorno;
}

lockByLua función pública ($ clave, expiran $ = 5)
{
$ script = <<< EOF

clave local = teclas [1]
valor local = ARGV [1]
ttl local = ARGV [2]

si (redis.call ( 'setnx' llave, valor) == 1) y luego
de regreso redis.call ( 'expirará', llave, ttl)
elseif (redis.call ( 'ttl', clave) == -1) entonces
redis.call retorno ( 'expirará', clave, TTL)
final

devolver 0
EOF;

$ this -> _ lockFlag = MD5 (microtime (verdadero));
return $ this -> _ eval ($ guión, [$ key, $ this -> _ lockFlag, $ expirará]);
}

la función pública de desbloqueo ($ clave)
{
$ script = <<< EOF

clave local = teclas [1]
valor local = ARGV [1]

si (redis.call ( 'existe', clave) == 1 y redis.call ( 'conseguir', clave) == valor)
a continuación,
volver redis.call ( 'del', clave)
final

devolver 0

EOF;

if ($ this -> _ lockFlag) {
return $ this -> _ eval ($ guión, [$ key, $ this -> _ lockFlag]);
}
}

_eval función privada ($ guión, array $ params, $ keyNum = 1)
{
$ de hash = $ this -> _ redescubrir> guión ( 'carga', $ script);
return $ this -> _ redescubrir> evalSha ($ hachís, $ params, $ keyNum);
}

}

$ RedisLock RedisLock = new ();

$ = clave 'bloqueo';
if ($ redisLock-> lockByLua ($ key)) {
// hacer ...
$ redisLock-> desbloqueo ($ key);
}

Supongo que te gusta

Origin www.cnblogs.com/myJuly/p/12640948.html
Recomendado
Clasificación