O Discourse utiliza amplamente o bloqueio (lock) do Redis como mecanismo de sincronização. A implementação do bloqueio do Redis no Discourse (como mostrado abaixo) pode ser aprimorada para usar menos comandos do Redis, reduzindo o tempo de ida e volta (round-trip) e o custo de execução no Redis.
Como podemos aprimorá-lo
Tanto lock quanto unlock utilizam Transações do Redis. O processo de lock poderia ser simplificado para o código abaixo.
WATCH key
GET key # determina se a chave expirou
MULTI
SET key
EXPIRE key, expire_time + 1
A razão para usar Transações do Redis (assumi) parece ser a de verificar se a chave expirou antes de realmente defini-la.
Mas acho que poderíamos simplesmente usar o comando SETEX fornecido pelo Redis, que define uma chave com um tempo de expiração. Na verdade, a Documentação do Redis SETEX o usa como exemplo para substituir SET e EXPIRE por SETEX.
Aqui estão os argumentos para por que devemos substituí-lo:
- Definir o valor como tempo de expiração e verificá-lo antes de definir a chave é desnecessário. O mecanismo de TTL é suficiente para garantir que a chave expire corretamente.
- Mesmo que decidamos usar o tempo de expiração como valor, não precisamos de nenhuma transação. Como fornecer atomicidade entre o
GET(linha 2 no código acima) eMULTIeEXECnão oferece nada. Isso ocorre porque, se o bloqueio não for adquirido, ele será refeito.
Uma nota histórica
Investiguei o histórico de commits do git para obter mais informações. Parece que, quando o bloqueio do Redis foi introduzido, não utilizávamos o TTL fornecido pelo Redis. O recurso de TTL foi introduzido muito depois.
Portanto, acho que podemos dar um passo adiante e remover completamente as Transações do Redis.