Análise do código-fonte do Redis: explicação detalhada da biblioteca de classes de super utilitário Redis Redisson

Por favor, adicione a descrição da imagem

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. .
insira a descrição da imagem aqui
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

Acho que você gosta

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