Análisis del código fuente de Redis: explicación detallada de la biblioteca de clases de superutilidad de Redis Redisson

Por favor agregue la descripción de la imagen

Biblioteca de clases de herramientas de Redisson

Recomiendo una biblioteca de clases de herramientas basada en el desarrollo de Redis. ¡Esta biblioteca de clases proporciona muchas funciones prácticas, como limitación de corriente, filtro de floración, bloqueo distribuido, etc.!

<dependency>
  <groupId>org.redisson</groupId>
  <artifactId>redisson</artifactId>
  <version>3.16.8</version>
</dependency>

Hoy solo analizaremos la implementación de bloqueos distribuidos Redisson proporciona muchas formas de bloqueo, como bloqueos sin bloqueo, bloqueos de bloqueo y bloqueos justos.

Además, se proporciona una función de retraso automático. Cuando una tarea no se completa, Redisson continuará extendiendo el período de bloqueo a través de Watch Dog.

Bloqueo de adquisición de bloqueo

// 阻塞式获取锁,并且是重入锁
RLock lock = client.getLock("testLock");
try {
    
    
    lock.lock();
    lock.lock();

	// 执行业务逻辑
	
} finally {
    
    
    lock.unlock();
    lock.unlock();
}

adquisición de bloqueo sin bloqueo

RLock lock = client.getLock("lock");
if (lock.tryLock()) {
    
    
    System.out.println("获锁成功");
} else {
    
    
    System.out.println("获锁失败");
}

¿Cómo implementa Redisson un bloqueo de reentrada?

secuencia de comandos de ejecución de bloqueo

entrada de guión

parámetro sentido
LLAVES[1] nombre de bloqueo
ARGV[1] Tiempo de espera de bloqueo (milisegundos)
ARGV[2] ID único del cliente: ID de subproceso
// 锁不存在
if (redis.call('exists', KEYS[1]) == 0) then
    // 新建锁,加锁次数设为1,并设置超时时间
    redis.call('hincrby', KEYS[1], ARGV[2], 1);
    redis.call('pexpire', KEYS[1], ARGV[1]);
    return nil;
end;
if (redis.call('hexists', KEYS[1], ARGV[2]) == 1) then
    // 当前线程已经获取到锁了,将加锁次数加1
    redis.call('hincrby', KEYS[1], ARGV[2], 1);
    redis.call('pexpire', KEYS[1], ARGV[1]);
    return nil;
end;
// 加锁失败
return redis.call('pttl', KEYS[1]);

Devuelve cero si el bloqueo es exitoso; de lo contrario, devuelve el tiempo restante del bloqueo.

Desbloquear secuencia de comandos de ejecución

entrada de guión

parámetro sentido
LLAVES[1] nombre de bloqueo
LLAVES[2 Desbloquee el canal del mensaje, el nombre del canal, redisson_lock__channel:{lock name}
ARGV[1] Fijo en 0, Redisson define el mensaje de desbloqueo para que se fije en 0
ARGV[2] tiempo de espera de bloqueo
ARGV[3] ID único del cliente: ID de subproceso
// 为0表示锁不存在
if (redis.call('hexists', KEYS[1], ARGV[3]) == 0) then
    return nil;
end;
// 将加锁次数减1
local counter = redis.call('hincrby', KEYS[1], ARGV[3], -1);
if (counter > 0) then
    // 当前线程持有锁,设置超时时间
    redis.call('pexpire', KEYS[1], ARGV[2]);
    return 0;
else
	// 加锁次数为0了,直接删除锁,并广播释放锁的消息
    redis.call('del', KEYS[1]);
    redis.call('publish', KEYS[2], ARGV[1]);
    return 1;
end;
return nil;

¿Por qué quieres publicar un mensaje cuando el desbloqueo es exitoso?

Debido a que el subproceso que adquiere el bloqueo mediante el bloqueo no sigue intentando adquirir el bloqueo todo el tiempo, se bloqueará.Cuando reciba el mensaje de desbloqueo, se despertará y comenzará a tomar el bloqueo nuevamente.

¿Cómo implementa Redisson el retraso automático de los bloqueos?

Para evitar que el bloqueo se libere correctamente, generalmente necesitamos establecer un tiempo de espera para el bloqueo, pero esto generará nuevos problemas.

Si el tiempo de espera del bloqueo se establece en 10 s, pero la tarea no se ejecuta dentro de los 10 s, el bloqueo se liberará y otros subprocesos tendrán problemas para adquirir el bloqueo.

Para solucionar este problema, Redisson proporciona un mecanismo de retardo automático del perro guardián, es decir, cuando el bloqueo es exitoso. Abra un subproceso en segundo plano, pase el threadId del bloqueo exitoso y el subproceso en segundo plano verifica cada 10 segundos para ver si el subproceso que actualmente tiene el bloqueo es el threadId. .
inserte la descripción de la imagen aquí
Cabe señalar que el tiempo de espera especificado no se puede mostrar al bloquear, de lo contrario, el perro guardián no tendrá efecto.

Cuando el tiempo de espera del bloqueo especificado no se muestra al bloquear, el tiempo de espera del bloqueo es la propiedad lockWatchdogTimeout de la clase Config. El valor predeterminado de esta propiedad es 30 s (configurable) y el tiempo para la verificación automática del mecanismo de vigilancia siempre es igual al tiempo de espera del bloqueo 1/3

Blog de referencia

[1]https://www.cnblogs.com/huangwentian/p/14622441.html?share_token=901429ee-a792-4f2a-87f9-20c47b7cc91c

Supongo que te gusta

Origin blog.csdn.net/zzti_erlie/article/details/123307897
Recomendado
Clasificación