# Un blocco Redis più efficiente

**URL:** <https://meta.discourse.org/t/a-more-efficient-redis-lock/177841>\
**Category:** Development\
**Created:** [31 Gennaio 2021, 1:10pm UTC](https://meta.discourse.org/t/a-more-efficient-redis-lock/177841 "2021-01-31T13:10:02Z")\
**Posts on this page:** 1\
**Showing post:** 1

<div class="post-metadata">

**Author:** ![concerto](https://avatars.discourse-cdn.com/v4/letter/c/dec6dc/32.png) [@concerto](https://meta.discourse.org/u/concerto)\
**Post date:** [31 Gennaio 2021, 1:10pm UTC](https://meta.discourse.org/t/a-more-efficient-redis-lock/177841/1 "2021-01-31T13:10:02Z")

</div>

Discourse utilizza ampiamente il lock Redis come meccanismo di sincronizzazione. L’implementazione del lock Redis di Discourse (come mostrato di seguito) può essere ottimizzata per ridurre il numero di comandi Redis, diminuendo così il tempo di round-trip e i costi di esecuzione su Redis.

> <https://github.com/discourse/discourse/blob/363170513e7be3e7fa1500ac640561e0e3c45e78/lib/distributed_mutex.rb#L84-L106>

## Come possiamo migliorarlo

Sia `lock` che `unlock` utilizzano le [Transazioni Redis](https://redis.io/topics/transactions). Il processo di `lock` potrebbe essere semplificato nel codice riportato qui sotto:

```ruby
WATCH key
GET key # determina se la chiave è scaduta
MULTI
SET key
EXPIRE key, expire_time + 1

```

Il motivo per cui si utilizza la transazione Redis (come ipotizzo) sembra essere la necessità di verificare se la chiave è scaduta prima di impostarla effettivamente.

Tuttavia, penso che potremmo semplicemente utilizzare il comando `SETEX` fornito da Redis, che imposta una chiave con un tempo di scadenza. Infatti, la [documentazione Redis SETEX](https://redis.io/commands/setex) lo utilizza come esempio per sostituire `SET & EXPIRE` con `SETEX`.

Ecco gli argomenti a favore della sostituzione:

1. Impostare il valore come tempo di scadenza e verificarlo prima di impostare la chiave è superfluo. Il meccanismo TTL è sufficiente a garantire che la chiave scada correttamente.
2. Anche se decidessimo di utilizzare il tempo di scadenza come valore, non avremmo bisogno di alcuna transazione. Poiché garantire l’atomicità tra `GET` (riga 2 nel codice sopra) e `MULTI & EXEC` non aggiunge alcun valore. Questo perché, se il lock non viene acquisito, verrà riprovato.

## Nota storica

Ho approfondito la cronologia dei commit Git per raccogliere maggiori informazioni. Sembra che quando il lock Redis è stato [introdotto](https://github.com/discourse/discourse/commit/ed45a1dce363e734642b78e238f88d9874be7680), non venisse utilizzato il TTL fornito da Redis. La funzionalità TTL è stata introdotta [molto più tardi](https://github.com/discourse/discourse/commit/7c7098c70056e1a3c2a8a9b366a793994b62dee8).

Quindi, ipotizzo che potremmo fare un passo in più ed eliminare completamente le transazioni Redis.

---

_[View the full topic](https://meta.discourse.org/t/a-more-efficient-redis-lock/177841)._
