Maison  >  Article  >  Java  >  Comment utiliser les verrous distribués en Java pour réaliser la synchronisation des systèmes distribués ?

Comment utiliser les verrous distribués en Java pour réaliser la synchronisation des systèmes distribués ?

王林
王林original
2023-08-03 08:43:481384parcourir

Comment utiliser les verrous distribués en Java pour réaliser la synchronisation des systèmes distribués ?

Introduction :
Dans un système distribué, des conflits de données et des problèmes de concurrence peuvent survenir lorsque plusieurs nœuds accèdent à des ressources partagées en même temps. Afin de garantir la cohérence des données, nous devons utiliser des verrous distribués pour réaliser la synchronisation des systèmes distribués. Java propose diverses façons d'implémenter des verrous distribués. Cet article présentera les méthodes d'implémentation de verrous distribués basées sur ZooKeeper et Redis, avec des exemples de code.

1. Implémentation de verrouillage distribué basée sur ZooKeeper
ZooKeeper est un service de coordination distribué, qui fournit un mécanisme de verrouillage distribué pour résoudre les problèmes de synchronisation dans les systèmes distribués. Voici un exemple de code qui utilise ZooKeeper pour implémenter des verrous distribués :

import org.apache.zookeeper.*;

import java.io.IOException;
import java.util.Collections;
import java.util.List;

public class ZooKeeperDistributedLock implements Watcher {
    private ZooKeeper zooKeeper;
    private String lockPath;
    private String currentPath;
    private String waitPath;

    public ZooKeeperDistributedLock(String connectString, int sessionTimeout, String lockPath) throws IOException {
        zooKeeper = new ZooKeeper(connectString, sessionTimeout, this);
        this.lockPath = lockPath;
    }

    public void lock() throws KeeperException, InterruptedException {
        if (tryLock()) {
            return;
        }

        while (true) {
            List<String> children = zooKeeper.getChildren(lockPath, false);
            Collections.sort(children);

            int index = children.indexOf(currentPath.substring(lockPath.length() + 1));
            if (index == 0) {
                return;
            }

            waitPath = lockPath + "/" + children.get(index - 1);
            zooKeeper.exists(waitPath, true);
            synchronized (this) {
                wait();
            }
        }
    }

    public void unlock() throws KeeperException, InterruptedException {
        zooKeeper.delete(currentPath, -1);
    }

    private boolean tryLock() throws KeeperException, InterruptedException {
        currentPath = zooKeeper.create(lockPath + "/lock", new byte[0], ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode.EPHEMERAL_SEQUENTIAL);
        List<String> children = zooKeeper.getChildren(lockPath, false);
        Collections.sort(children);
        if (currentPath.endsWith(children.get(0))) {
            return true;
        }
        String currentPathName = currentPath.substring(lockPath.length() + 1);
        int index = children.indexOf(currentPathName);
        if (index < 0) {
            throw new IllegalStateException("Node " + currentPathName + " no longer exists.");
        } else {
            waitPath = lockPath + "/" + children.get(index - 1);
            zooKeeper.exists(waitPath, true);
            synchronized (this) {
                wait();
            }
            return false;
        }
    }

    @Override
    public void process(WatchedEvent event) {
        if (waitPath != null && event.getType() == Event.EventType.NodeDeleted && event.getPath().equals(waitPath)) {
            synchronized (this) {
                notifyAll();
            }
        }
    }
}

2. Implémentation de verrous distribués basée sur Redis
Redis est un système de stockage clé-valeur hautes performances qui fournit certaines opérations atomiques pour implémenter des verrous distribués. Voici un exemple de code permettant d'utiliser Redis pour implémenter des verrous distribués :

import redis.clients.jedis.Jedis;

public class RedisDistributedLock {
    private Jedis jedis;
    private String lockKey;
    private String requestId;

    public RedisDistributedLock(String host, int port, String password, String lockKey, String requestId) {
        jedis = new Jedis(host, port);
        jedis.auth(password);
        this.lockKey = lockKey;
        this.requestId = requestId;
    }

    public boolean lock(long expireTimeMillis) {
        String result = jedis.set(lockKey, requestId, "NX", "PX", expireTimeMillis);
        return "OK".equals(result);
    }

    public boolean unlock() {
        Long result = (Long) jedis.eval(
                "if redis.call('get', KEYS[1]) == ARGV[1] then " +
                "return redis.call('del', KEYS[1]) " +
                "else " +
                "return 0 " +
                "end",
                1,
                lockKey,
                requestId);
        return result != null && result == 1;
    }
}

Conclusion :
Cet article présente deux méthodes d'utilisation des verrous distribués en Java pour réaliser la synchronisation des systèmes distribués : basée sur ZooKeeper et Redis. Que vous utilisiez ZooKeeper ou Redis, vous pouvez réaliser efficacement la synchronisation des systèmes distribués et garantir la cohérence des données. Dans les projets réels, le choix d'une solution de verrouillage distribué appropriée doit être pondéré en fonction des besoins spécifiques et des exigences de performances. J'espère que cet article vous sera utile, merci d'avoir lu !

Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

Déclaration:
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn