Biblioteca de classes da ferramenta Redisson
Eu recomendo uma biblioteca de classes de ferramentas baseada no desenvolvimento Redis. Esta biblioteca de classes fornece muitas funções práticas, como limitação de corrente, filtro bloom, bloqueio distribuído, etc.!
<dependency>
<groupId>org.redisson</groupId>
<artifactId>redisson</artifactId>
<version>3.16.8</version>
</dependency>
Analisaremos apenas a implementação de bloqueios distribuídos hoje. O Redisson fornece muitas maneiras de bloqueio, como bloqueios sem bloqueio, bloqueios de bloqueio e bloqueios justos.
Além disso, é fornecida uma função de atraso automático. Quando uma tarefa não é concluída, o Redisson continuará a estender o período de bloqueio através do Watch Dog.
Bloqueando adquirir bloqueio
// 阻塞式获取锁,并且是重入锁
RLock lock = client.getLock("testLock");
try {
lock.lock();
lock.lock();
// 执行业务逻辑
} finally {
lock.unlock();
lock.unlock();
}
aquisição de bloqueio sem bloqueio
RLock lock = client.getLock("lock");
if (lock.tryLock()) {
System.out.println("获锁成功");
} else {
System.out.println("获锁失败");
}
Como o Redisson implementa um bloqueio reentrante?
script de execução de bloqueio
entrada de script
parâmetro | significado |
---|---|
CHAVES[1] | nome de bloqueio |
ARGV[1] | Tempo limite de bloqueio (milissegundos) |
ARGV[2] | ID exclusivo do cliente: ID do thread |
// 锁不存在
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]);
Retorna nil se o bloqueio for bem-sucedido, caso contrário, retorna o tempo restante do bloqueio
Desbloqueie o script de execução
entrada de script
parâmetro | significado |
---|---|
CHAVES[1] | nome de bloqueio |
CHAVES[2 | Desbloqueie o canal da mensagem, o nome do canal, redisson_lock__channel:{lock name} |
ARGV[1] | Fixo em 0, Redisson define a mensagem de desbloqueio a ser fixada em 0 |
ARGV[2] | tempo limite de bloqueio |
ARGV[3] | ID exclusivo do cliente: ID do thread |
// 为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 que você deseja publicar uma mensagem quando o desbloqueio é bem-sucedido?
Como a thread que adquire o bloqueio por bloqueio não fica tentando adquirir o bloqueio o tempo todo, ele irá bloquear, quando receber a mensagem de desbloqueio, ele acordará e começará a pegar o bloqueio novamente.
Como o Redisson implementa o atraso automático de bloqueios?
Para evitar que o bloqueio seja liberado corretamente, geralmente precisamos definir um tempo limite para o bloqueio, mas isso apresentará novos problemas.
Se o tempo limite do bloqueio for definido como 10s, mas a tarefa não for executada em 10s, o bloqueio será liberado e outros threads terão problemas para adquirir o bloqueio.
Para solucionar este problema, a Redisson disponibiliza um mecanismo de retardo automático de watch dog, ou seja, quando a trava é bem sucedida. Abra um thread em segundo plano, passe o threadId do bloqueio bem-sucedido e o thread em segundo plano verifica a cada 10s para ver se o thread que está mantendo o bloqueio é o threadId. .
Deve-se notar que o tempo limite especificado não pode ser exibido ao bloquear, caso contrário, o watchdog não terá efeito
Quando o tempo limite do bloqueio especificado não é exibido durante o bloqueio, o tempo limite do bloqueio é a propriedade lockWatchdogTimeout da classe Config. O valor padrão dessa propriedade é 30s (configurável) e o tempo para verificação automática do watchdog é sempre igual ao tempo limite do bloqueio. 1/3
Blogue de referência
[1]https://www.cnblogs.com/huangwentian/p/14622441.html?share_token=901429ee-a792-4f2a-87f9-20c47b7cc91c