Un bloqueo de Redis más eficiente

Discourse utiliza ampliamente el bloqueo de Redis como mecanismo de sincronización. La implementación de Discourse para el bloqueo de Redis (como se muestra a continuación) podría mejorarse reduciendo la cantidad de comandos de Redis, lo que disminuiría el tiempo de ida y vuelta y el costo de ejecución en Redis.

Cómo podríamos mejorarlo

Tanto lock como unlock utilizan Transacciones de Redis. El proceso de lock podría simplificarse al siguiente código:

WATCH key
GET key # determinar si la clave ha expirado
MULTI
SET key
EXPIRE key, expire_time + 1

La razón para utilizar una Transacción de Redis (según mi suposición) parece ser que verifica si la clave ha expirado antes de establecerla realmente.

Sin embargo, creo que podríamos simplemente usar el comando SETEX proporcionado por Redis, que establece una clave con un tiempo de expiración. De hecho, la documentación de Redis SETEX lo utiliza como ejemplo para reemplazar SET & EXPIRE con SETEX.

Estos son los argumentos para justificar su reemplazo:

  1. Establecer el valor como tiempo de expiración y verificarlo antes de establecer la clave es innecesario. El mecanismo TTL es suficiente para garantizar que la clave expire correctamente.
  2. Incluso si decidimos usar el tiempo de expiración como valor, no necesitamos ninguna transacción. Proporcionar atomicidad entre GET (línea 2 del código anterior) y MULTI & EXEC no aporta nada, ya que si no se adquiere el bloqueo, se reintentará.

Nota histórica

Investigué el historial de commits de git para obtener más información. Parece que cuando se introdujo el bloqueo de Redis, no se utilizaba el TTL proporcionado por Redis. La función TTL se introdujo mucho después.

Por lo tanto, creo que podríamos dar un paso más y eliminar por completo las transacciones de Redis.

Según Develop with Redis | Docs

Probablemente podamos descartar toda la transacción y hacer un set con las opciones px y nx