Într-o arhitectură de microservicii, sincronizarea acțiunilor critice concurente (evitarea plății duble a unei comenzi, procesarea unică a unei facturi, atribuirea unui loc în avion) necesită un blocaj distribuit (Distributed Lock) sigur și ultra-rapid.
Implementarea naivă cu SETNX urmat de EXPIRE este profund eronată: dacă procesul cade între cele două comenzi, blocajul nu va expira niciodată, provocând un deadlock permanent în întregul sistem!
# 1. Dobândirea atomică a blocajului (Lock Acquisition):
# - 'NX': Setează cheia DOAR dacă nu există deja (garantează excluderea mutuală).
# - 'PX 30000': Atribuie un timp de viață (TTL) de 30.000 milisecunde (previne deadlock dacă worker-ul crapă).
# - 'token_uuid_unic': Un identificator unic generat aleator (UUIDv4) per încercare de blocare.
SET lock:comanda:9812 "a8f1b620-3b2a-4c28-bb84-9092c710f441" NX PX 30000
# Dacă returnează 'OK' -> Blocajul a fost obținut!
# Dacă returnează '(nil)' -> Resursa este ocupată de un alt worker!
# 2. Eliberarea Sigură a Blocajului (Lock Release):
# ATENȚIE CRITICĂ: Nu folosiți niciodată comanda simplă 'DEL lock:comanda:9812'!
# Dacă execuția sarcinii a durat 31 de secunde, blocajul a expirat automat și a fost preluat de Worker-ul B.
# Un DEL necondiționat lansat de Worker-ul A ar șterge blocajul legitim al Worker-ului B!
# Soluția: Un script Lua care verifică dacă token-ul curent corespunde înainte de ștergere:
EVAL "if redis.call('get', KEYS[1]) == ARGV[1] then return redis.call('del', KEYS[1]) else return 0 end" 1 lock:comanda:9812 "a8f1b620-3b2a-4c28-bb84-9092c710f441"
Algoritmul Redlock pentru Clustere Multi-Master
Dacă folosiți o arhitectură clasică Master-Replica, un failover neașteptat poate duce la pierderea blocajului (deoarece replicarea Redis este asincronă). Pentru garanții matematice stricte de toleranță la erori, algoritmul Redlock (propus de antirez) presupune:
- Rularea a $N$ instanțe Redis Master complet independente (de exemplu $N=5$).
- Clientul încearcă să obțină blocajul pe toate cele 5 noduri secvențial, folosind același token și un timeout scurt.
- Blocajul este considerat valid dacă a fost obținut pe majoritatea nodurilor ($\ge 3$ din 5) într-un timp total mai mic decât durata de viață (TTL) a blocajului.