Implémentation de verrous distribués avec Redis : solutions et approches

Introduction aux verrous distribués

Dans les systèmes distribués, la cohérence des données partagées entre plusieurs services nécessite des mécanismes de synchronisation. Les verrous distribués garantissent qu'une seule opération modifie une ressource à un instant donné, évitant ainsi les conflits et les incohérences.

Méthode 1 : Utilisation basique de SET avec NX

La commande SET de Redis permet de définir une clé avec l'option NX pour une acquisition atomique. Cela évite les conflits lors de la tentative de verrouillage par plusieurs clients.


String cleVerrou = "inventaire_lock";
String identifiantClient = UUID.randomUUID().toString();
Boolean acquisition = template.opsForValue().setIfAbsent(cleVerrou, identifiantClient);
if (acquisition) {
    // Traitement critique
    template.delete(cleVerrou);
}

Cette approche peut échouer si le service tombe en panne avant la libération du verrou, laissant la clé bloquée indéfiniment.

Méthode 2 : Ajout d'une expiration temporelle

Pour éviter les blocages permanents, on attribue une durée de vie à la clé lors de sa création. Cela garantit une libération automatique en cas d'anomalie.


String cleVerrou = "inventaire_lock";
String identifiantClient = UUID.randomUUID().toString();
Long delaiExpiration = 10L;
Boolean acquisition = template.opsForValue().setIfAbsent(cleVerrou, identifiantClient, delaiExpiration, TimeUnit.SECONDS);
if (acquisition) {
    // Traitement critique
    template.delete(cleVerrou);
}

Cependant, si le traitement dépasse le délai d'expiration, un autre client peut acquérir le verrou, menant à des suppressions erronées de clés.

Méthode 3 : Validation de l'identifiant avant suppression

Pour s'assuerr qu'un client ne supprime que le verrou qu'il a créé, on compare l'identifiant stocké avant la suppression.


String cleVerrou = "inventaire_lock";
String identifiantClient = UUID.randomUUID().toString();
Long delaiExpiration = 10L;
try {
    Boolean acquisition = template.opsForValue().setIfAbsent(cleVerrou, identifiantClient, delaiExpiration, TimeUnit.SECONDS);
    if (!acquisition) {
        return "Échec d'acquisition du verrou.";
    }
    // Traitement critique
} finally {
    String valeurActuelle = template.opsForValue().get(cleVerrou);
    if (identifiantClient.equals(valeurActuelle)) {
        template.delete(cleVerrou);
    }
}

La vérification et la suppression ne sont pas atomiques, ce qui peut causer des problèmes en environnement concrurentiel.

Méthode 4 : Utilisation de scripts LUA pour l'atomicité

Un script LUA exécuté sur Redis permet de combiner la vérification et la suppression en une seule opération atomique, éliminant ainsi les conditions de course.


String cleVerrou = "inventaire_lock";
String identifiantClient = UUID.randomUUID().toString();
try {
    Boolean acquisition = template.opsForValue().setIfAbsent(cleVerrou, identifiantClient, 10L, TimeUnit.SECONDS);
    if (!acquisition) {
        return "Échec d'acquisition du verrou.";
    }
    // Traitement critique
} finally {
    String scriptLUA = "if redis.call('get', KEYS[1]) == ARGV[1] then return redis.call('del', KEYS[1]) else return 0 end";
    jedis.eval(scriptLUA, Collections.singletonList(cleVerrou), Collections.singletonList(identifiantClient));
}

Cette solution résout les problèmes d'atomicité, mais ne gère pas le renouvellement automatique des verrous dans les environnements à haute latence.

Méthode 5 : Utilisation de Redisson pour une gestion avancée

Redisson offre une implémentation complète des verrous distribués avec des fonctionnalités telles que le renouvellement automatique et la redondance en cluster, basée sur l'algorithme RedLock.


RLock verrou = redisson.getLock("inventaire_lock");
verrou.lock();
try {
    // Traitement critique
} finally {
    if (verrou.isHeldByCurrentThread()) {
        verrou.unlock();
    }
}

Redisson simplifie la gestion des verrous distribués en intégrant des mécanismes de fiabilité et de performance optimisés pour les architectures complexes.

Étiquettes: Redis Distributed Locks Java Spring Boot Redisson

Publié le 7 juin à 04h12