Discourse nutzt Redis-Locks weit verbreitet als Synchronisationsmechanismus. Die Implementierung von Redis-Locks in Discourse (wie unten gezeigt) könnte optimiert werden, um weniger Redis-Befehle zu verwenden, was die Round-Trip-Zeit und die Kosten für die Ausführung durch Redis senkt.
Wie wir dies verbessern können
Sowohl lock als auch unlock verwenden Redis-Transaktionen. Der lock-Prozess könnte auf den folgenden Code vereinfacht werden:
WATCH key
GET key # Prüfen, ob der Key abgelaufen ist
MULTI
SET key
EXPIRE key, expire_time + 1
Der Grund für die Verwendung von Redis-Transaktionen (meine Annahme) scheint darin zu bestehen, dass geprüft wird, ob der Key abgelaufen ist, bevor er tatsächlich gesetzt wird.
Ich denke jedoch, dass wir einfach den von Redis bereitgestellten SETEX-Befehl verwenden könnten, der einen Key mit einer Ablaufzeit setzt. Tatsächlich wird in der Redis SETEX-Dokumentation dies als Beispiel angeführt, um SET & EXPIRE durch SETEX zu ersetzen.
Hier sind die Argumente, warum wir dies ersetzen sollten:
- Das Setzen des Werts auf die Ablaufzeit und das Prüfen davon vor dem Setzen des Keys ist unnötig. Der TTL-Mechanismus reicht aus, um sicherzustellen, dass der Key korrekt abläuft.
- Selbst wenn wir uns entscheiden, die Ablaufzeit als Wert zu verwenden, benötigen wir keine Transaktion. Da die Bereitstellung von Atomizität zwischen
GET(Zeile 2 im obigen Code) undMULTI&EXECkeinen Mehrwert bietet. Das liegt daran, dass bei einem nicht erworbenen Lock einfach erneut versucht wird.
Ein historischer Hinweis
Ich habe mich in der Git-Commit-Historie nach weiteren Informationen umgesehen. Es scheint, dass wir beim Einführen des Redis-Locks die von Redis bereitgestellte TTL noch nicht verwendet haben. Die TTL-Funktion wurde viel später eingeführt.
Daher vermute ich, dass wir einen Schritt weitergehen und Redis-Transaktionen komplett entfernen könnten.