Zpět na domů

RedLock.NET: distribuované zámky v .NET

Článek popisuje implementaci distribuovaných zámků v .NET s použitím RedLock.NET a alternativ přes PostgreSQL. Jsou porovnány standardní primitivy, Mutex, DB zámky. Uvedeny SQL příklady a best practices pro mikroslužby v Kubernetes.

Distribuované zámky v .NET: RedLock vs DB přístupy
Advertisement 728x90

Implementace distribuovaných zámků v .NET s RedLock.NET

Distribuované zámky zajišťují exkluzivní přístup k kritickým sekcím v systémech s více instancemi služeb. To je aktuální pro mikro služby v Kubernetes, kde pody nebo různé služby soutěží o zdroje. Hlavní cíl – atomické provádění operací, jako je aktualizace klíčových dat v DB nebo volání externích API.

Typické scénáře:

  • Změna obchodně kritických hodnot v databázi.
  • Odesílání požadavků do regulačních systémů (např. analogy Čestného Znaku).
  • Synchronizace mezi pody jednoho mikro služby nebo služebami v orchestraci/choreografii.

Standardní .NET primitivy jako SemaphoreSlim, AsyncLock nebo lock nejsou vhodné kvůli fyzické oddělenosti instancí. Mutex funguje na Windows, ale je problematický v asynchronním kódu a Docker kontejnerech.

Google AdInline article slot

Přehled RedLock.NET

RedLock.NET – knihovna pro implementaci algoritmu RedLock na .NET. Poslední stabilní verze 2.3.2 (2022). Balíček prošel bezpečnostní kontroly, bez známých zranitelností. Autor aktivně řeší issues na GitHub.

Algoritmus RedLock využívá Redis cluster pro distribuované zámky s TTL a zajišťuje bezpečnost i při síťových selháních. Knihovna zapouzdřuje logiku: vytváření, prodlužování a mazání zámků.

Alternativy: zámky přes DB

Tabulka locks v PostgreSQL

Klasický přístup – speciální tabulka pro zámky:

Google AdInline article slot
CREATE TABLE locks (
    resource VARCHAR(100) PRIMARY KEY,
    locked_by VARCHAR(100),
    locked_at TIMESTAMPTZ DEFAULT NOW(),
    expires_at TIMESTAMPTZ
);

Atomární INSERT se zpracováním konfliktů:

INSERT INTO locks (resource, locked_by, expires_at)
VALUES (@resource, @locked_by, NOW() + (@timespan || ' seconds')::interval)
ON CONFLICT (resource) DO UPDATE
SET locked_by = EXCLUDED.locked_by,
    expires_at = EXCLUDED.expires_at
WHERE locks.expires_at < NOW()
RETURNING locked_by;

Logika:

  • Pokud zámek neexistuje – vytvoří se nový s TTL.
  • Pokud zámek vypršel – aktualizuje se.
  • Pokud je aktivní – vrátí prázdný výsledek.

Požadavky:

Google AdInline article slot
  • Unikátní resource pro operaci.
  • Unikátní locked_by (GUID nebo instance ID + thread ID).

Úrovně izolace

SERIALIZABLE zajišťuje atomárnost bez dalších tabulek, ale snižuje propustnost. V enterprise prostředí DBA zřídka schválí kvůli zátěži. Upřednostňují se UPSERT přístupy s READ COMMITTED.

Srovnání přístupů

| Přístup | Výhody | Nevýhody |

|--------------|---------------------------------|---------------------------------------|

| .NET primitivy | Jednoduchost, nízká latence | Pouze single instance |

| Mutex | Sync na úrovni OS | Ne pro Docker/Linux, async problémy |

| DB zámky | Integrace s DB | Overhead na DB, problémy se škálováním|

| RedLock.NET | Vysoká dostupnost, TTL | Závislost na Redis |

DB zámky jsou vhodné pro jednoduché případy s nízkou frekvencí. RedLock.NET – pro systémy s vysokým zatížením se zárukami.

Praktická implementace RedLock.NET

Instalace: dotnet add package RedLock.net. Vytvořte RedLockFactory s Redis endpoints:

var multiplexer = new ConnectionMultiplexer(...);
var factory = RedLockFactory.Create(...);
using var @lock = await factory.CreateLockAsync(resource, expiry);
if (@lock.IsAcquired) {
    // critical section
}

Klíčové parametry:

  • resource: řetězec-identifikátor (key v Redis).
  • expiry: TimeSpan pro TTL.
  • Quorum: většina Redis nodů pro konsenzus.

Zpracování selhání: knihovna automaticky prodlužuje zámek při dlouhých operacích prostřednictvím IExtensibleLock.

Škálování a best practices

  • Používejte Redis Sentinel nebo Cluster pro HA.
  • Clock drift < 10ms mezi nodami.
  • Doba platnosti > 2x clock drift + doba operace.
  • Monitorujte míru selhání získání zámku.

V produkci kombinujte s circuit breaker pro externí volání v kritické sekci.

Co je důležité

  • RedLock.NET zajišťuje bezpečnost založenou na quoru bez single point of failure.
  • DB zámky jsou jednodušší, ale zranitelné vůči přetížení DB a neshkálovatelné.
  • Vždy nastavte TTL pro ochranu před zombie zámky.
  • Testujte pod zátěží se simulací síťového oddělení.
  • Pro .NET Core+ se vyhněte Mutex v kontejnerech.

— Editorial Team

Advertisement 728x90

Číst dál