Class DistributedLock
- Namespace
- UsluzionicaServer.Infrastructure.Redis
- Assembly
- UsluzionicaServer.dll
Distribuirani lock — obezbeđuje da posao izvrši TAČNO JEDNA instanca.
Zašto je potreban: BackgroundService se pokreće u svakom procesu. Sa dve
instance API-ja, BoostExpiryService bi u istom trenutku na obe krenuo da
oduzima BoostScore istim oglasima — pa bi svaki oglas bio umanjen dvaput.
MessageCleanupService bi dvaput brisao (bezopasno) ali bi i dvaput logovao
i dvaput opteretio bazu.
Mehanizam je Redis SET key value NX PX ttl:
NX → upiši SAMO ako ključ ne postoji (atomično, na strani Redis-a)
PX → automatski istekni posle ttl milisekundi
TTL je ono što ovo čini bezbednim. Ako instanca koja drži lock pukne ili joj neko povuče struju, lock se sam oslobodi posle TTL-a. Bez TTL-a bi jedan pad zauvek zaustavio taj posao na celom klasteru.
TTL zato mora biti DUŽI od najdužeg očekivanog trajanja posla. Ako posao traje duže, drugi ga preuzme dok prvi još radi — i vraćamo se na problem koji smo rešavali.
public sealed class DistributedLock
- Inheritance
-
DistributedLock
- Inherited Members
Constructors
- DistributedLock(RedisConnection, ILogger<DistributedLock>)
Distribuirani lock — obezbeđuje da posao izvrši TAČNO JEDNA instanca.
Zašto je potreban:
BackgroundServicese pokreće u svakom procesu. Sa dve instance API-ja,BoostExpiryServicebi u istom trenutku na obe krenuo da oduzima BoostScore istim oglasima — pa bi svaki oglas bio umanjen dvaput.MessageCleanupServicebi dvaput brisao (bezopasno) ali bi i dvaput logovao i dvaput opteretio bazu.Mehanizam je Redis
SET key value NX PX ttl: NX → upiši SAMO ako ključ ne postoji (atomično, na strani Redis-a) PX → automatski istekni posle ttl milisekundiTTL je ono što ovo čini bezbednim. Ako instanca koja drži lock pukne ili joj neko povuče struju, lock se sam oslobodi posle TTL-a. Bez TTL-a bi jedan pad zauvek zaustavio taj posao na celom klasteru.
TTL zato mora biti DUŽI od najdužeg očekivanog trajanja posla. Ako posao traje duže, drugi ga preuzme dok prvi još radi — i vraćamo se na problem koji smo rešavali.
Methods
- TryAcquireAsync(string, TimeSpan)
Pokušava da zauzme lock. Vraća objekat koji ga oslobađa pri dispose-u, ili null ako ga druga instanca već drži.
KAD REDIS NIJE DOSTUPAN vraća lock koji ništa ne radi — dakle posao se IZVRŠAVA. To je namerno: sa jednom instancom (razvoj, testovi, mali deployment) nema šta da se štiti, a odbijanje posla bi značilo da se boostovi nikad ne gase ako Redis ispadne.