# # Implémentation de verrous distribués en .NET avec RedLock.NET
Les verrous distribués permettent un accès exclusif aux sections critiques dans les systèmes comportant plusieurs instances de services. Cela est crucial pour les microservices dans Kubernetes, où les pods ou différents services se disputent les ressources. L'objectif principal est l'exécution atomique des opérations, comme la mise à jour de données clés en base de données ou l'appel d'API externes.
Scénarios typiques :
- Modification de valeurs critiques pour l'entreprise en base de données.
- Envoi de requêtes vers des systèmes réglementaires (par ex., équivalents de Chestny Znak).
- Synchronisation entre pods du même microservice ou services en orchestration/chorégraphie.
Les primitives standard .NET comme SemaphoreSlim, AsyncLock ou lock ne conviennent pas en raison de la séparation physique des instances. Mutex fonctionne sur Windows mais pose problème dans le code asynchrone et les conteneurs Docker.
Aperçu de RedLock.NET
RedLock.NET est une bibliothèque pour implémenter l'algorithme RedLock en .NET. La dernière version stable est la 2.3.2 (2022). Le package a passé les vérifications de sécurité sans vulnérabilités connues. L'auteur maintient activement les issues sur GitHub.
L'algorithme RedLock utilise un cluster Redis pour des verrous distribués avec TTL, garantissant la sécurité même en cas de pannes réseau. La bibliothèque encapsule la logique pour créer, prolonger et libérer les verrous.
Alternatives : Verrous via base de données
Table des verrous en PostgreSQL
L'approche classique consiste en une table dédiée aux verrous :
CREATE TABLE locks (
resource VARCHAR(100) PRIMARY KEY,
locked_by VARCHAR(100),
locked_at TIMESTAMPTZ DEFAULT NOW(),
expires_at TIMESTAMPTZ
);
INSERT atomique avec gestion des conflits :
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;
Logique :
- Si le verrou est absent, un nouveau est créé avec TTL.
- Si le verrou a expiré, il est mis à jour.
- S'il est actif, un résultat vide est retourné.
Exigences :
resourceunique par opération.locked_byunique (GUID ou ID d'instance + ID de thread).
Niveaux d'isolation
SERIALIZABLE garantit l'atomicité sans tables supplémentaires mais réduit le débit. Dans les environnements d'entreprise, les DBA l'approuvent rarement en raison de la charge. Les approches UPSERT avec READ COMMITTED sont préférées.
Comparaison des approches
| Approche | Avantages | Inconvénients |
|----------|-----------|---------------|
| Primitives .NET | Simplicité, faible latence | Une seule instance uniquement |
| Mutex | Synchronisation au niveau OS | Non adapté à Docker/Linux, problèmes asynchrones |
| Verrous en base de données | Intégration base de données | Surcharge base de données, problèmes d'évolutivité |
| RedLock.NET | Haute disponibilité, TTL | Dépendance Redis |
Les verrous en base de données conviennent bien aux cas simples à faible fréquence. RedLock.NET est idéal pour les scénarios à forte charge avec des garanties solides.
Implémentation pratique de RedLock.NET
Installation : dotnet add package RedLock.net. Créez une RedLockFactory avec les endpoints Redis :
var multiplexer = new ConnectionMultiplexer(...);
var factory = RedLockFactory.Create(...);
using var @lock = await factory.CreateLockAsync(resource, expiry);
if (@lock.IsAcquired) {
// section critique
}
Paramètres clés :
resource: identifiant chaîne (clé Redis).expiry:TimeSpanpour TTL.- Quorum : majorité des nœuds Redis pour consensus.
Gestion des erreurs : la bibliothèque prolonge automatiquement les verrous pour les opérations longues via IExtensibleLock.
Évolutivité et bonnes pratiques
- Utilisez Redis Sentinel ou Cluster pour la HA.
- Décalage d'horloge < 10 ms entre nœuds.
- Durée de validité > 2x décalage d'horloge + temps d'opération.
- Surveillez le taux d'échec d'acquisition de verrous.
En production, combinez avec des disjoncteurs de circuit pour les appels externes dans les sections critiques.
Points clés à retenir
- RedLock.NET fournit une sécurité basée sur quorum sans point de défaillance unique.
- Les verrous en base de données sont plus simples mais vulnérables à la surcharge de la base et ne s'échelonnent pas.
- Définissez toujours un TTL pour protéger contre les verrous zombies.
- Testez sous charge avec simulations de partition réseau.
- Pour .NET Core et versions ultérieures, évitez Mutex dans les conteneurs.
— Editorial Team
Aucun commentaire pour le moment.