Nota de operación: después de ingresar al redisson de github, seleccione la siguiente imagen para ingresar a la introducción del proyecto Redisson (documento chino)
Uno, el concepto de cerraduras distribuidas
El propósito de los bloqueos distribuidos es: en un entorno distribuido, para que una determinada operación (insertar un dato de la base de datos) se ejecute solo una vez, para evitar una serie de problemas causados por operaciones de datos repetidas, el comando setnx y lua en Los Redis se utilizan Script para implementar bloqueos distribuidos para resolver los problemas anteriores.
Dos, varias situaciones de uso del comando setnx
2.1 ¿Qué debo hacer si hay una excepción en el código comercial y el comando para ejecutar el bloqueo de liberación (eliminar bloqueo) no se puede ejecutar, lo que resulta en un interbloqueo (el bloqueo no se libera)?
La solución es: intente {} finalmente {} se puede usar para resolver el problema, pero si el código comercial se ejecuta y la máquina pierde energía repentinamente, ¿qué debo hacer?
La solución final es: establecer el tiempo de vencimiento del bloqueo, incluso si el bloqueo no se elimina, el bloqueo vencido se eliminará automáticamente
2.2. El parpadeo (tiempo de inactividad) entre el establecimiento del bloqueo y el establecimiento del tiempo de vencimiento seguirá siendo un punto muerto ¿Cómo solucionarlo?
La solución es: use el comando setnx ex de Redis, que es una combinación de configuración de bloqueo + configuración de tiempo de vencimiento, y también es una operación atómica.
2.3. Al eliminar el candado, debido al tiempo de espera del código comercial, el candado caduca antes y el candado de otra persona se elimina, ¿qué debo hacer?
2.4. Si el negocio se agota, otros subprocesos también se bloquearán y entrarán en la operación comercial, lo que resultará en operaciones comerciales repetidas.
Resuelva el problema anterior: al ocupar la cerradura, establezca el valor en uuid, al eliminar, compare
2.5. Dado que se compara el valor de uuid (para obtener el valor de Redis) y se elimina el valor, no se trata de una operación atómica. Al obtener el valor de uuid, puede llevar mucho tiempo, lo que da como resultado la eliminación final de el bloqueo de otro hilo. ¿Qué debo hacer?
Solución: compare el valor uuid + eliminar el valor después de una comparación exitosa = operación atómica, puede saberlo en el documento oficial de Redis, puede usar el script lua
2.6. La forma final es la siguiente: Al bloquear y desbloquear, asegúrese de atomicidad
Código final:
@Test
public void testRedisHadoop(){
String uuid = UUID.randomUUID().toString();
// 占锁(设置值),并且设置过期时间。这是一个Redis的原子命令
// NX和EX
Boolean lock = redisTemplate.opsForValue().setIfAbsent("lock", uuid, 300, TimeUnit.SECONDS);
if(lock){
// 加锁成功,执行业务
try{
System.out.println("业务执行。。。。");
}finally {
// 获取值对比+对比成功处理=原子操作------lua脚本
// 通过uuid来删除锁,以防删除别人的锁或者
// String lockValue = (String) redisTemplate.opsForValue().get("lock");
// if(uuid.equals(lockValue)){
// redisTemplate.delete("lock");
// }
//lua脚本
String script = "if redis.call(\"get\",KEYS[1]) == ARGV[1]\n" +
"then\n" +
" return redis.call(\"del\",KEYS[1])\n" +
"else\n" +
" return 0\n" +
"end";
//删除锁
Object lock1 = redisTemplate.execute(new DefaultRedisScript<Long>(script, Long.class), Arrays.asList("lock"), uuid);
}
}else {
System.out.println("获取锁失败,继续尝试");
testRedisHadoop();//自旋锁
}
}
Tres, cerradura distribuida de Redisson -------- cerradura reentrante
Si se llama al método b en el método a, a agrega un candado marcado como 1 yb también agrega un candado marcado como 1.
Si es un ** bloqueo reentrante, entonces cuando se ejecuta el método a, el método b interno no necesita esperar a que a libere el bloqueo, y utiliza directamente el bloqueo del método a.
Si se trata de un bloqueo no reentrante, ** entonces, cuando se ejecuta el método a, el método b interno debe esperar a que a libere el bloqueo 1 antes de tomar el bloqueo 1, y luego ejecutarlo.
3.1. Dos métodos de bloqueo y recarga para cerraduras reentrantes (consulte la figura siguiente)
Cuatro, bloqueo de lectura y escritura de redis
La función es: obtener los datos más recientes
El bloqueo de escritura es un bloqueo exclusivo (bloqueo de exclusión mutua, bloqueo exclusivo), el bloqueo de lectura es un bloqueo compartido.
Cuando el bloqueo de escritura está en funcionamiento, el bloqueo de lectura solo puede esperar. Si no hay ningún bloqueo de escritura en funcionamiento, el bloqueo de lectura se comparte, al igual que sin bloqueo.
4.2. Descripción complementaria del bloqueo de lectura-escritura
Leer + escribir: hay un bloqueo de lectura y la escritura debe esperar. ======= Cuando el bloqueo de lectura está en curso, el bloqueo de escritura debe esperar a que se libere el bloqueo de lectura (la ejecución está completa) antes de que pueda ejecutarse.
Leer + Leer: Equivalente al estado desbloqueado. Todos los bloqueos de lectura actuales se bloquearán correctamente al mismo tiempo.
Escribir + Leer: Leer bloqueo y esperar a que se libere el bloqueo de escritura
Escribir + Escribir: Modo de bloqueo (debe obtener hasta)
Resumen: Mientras haya un bloqueo de escritura, debe esperar.