54 votes

Contrôle distribué de la concurrence

Je travaille sur ce sujet depuis quelques jours maintenant, et j'ai trouvé plusieurs solutions mais aucune d'entre elles n'est incroyablement simple ou légère. Le problème est essentiellement le suivant : Nous avons un cluster de 10 machines, chacune d'entre elles exécutant le même logiciel sur une plateforme ESB multithread. Je peux gérer les problèmes de concurrence entre les threads sur la même machine assez facilement, mais qu'en est-il de la concurrence sur les mêmes données sur différentes machines ?

Essentiellement, le logiciel reçoit des demandes pour alimenter les données d'un client d'une entreprise à une autre via des services web. Cependant, le client peut ou non exister encore sur l'autre système. S'il n'existe pas, nous le créons via une méthode de service web. Cela nécessite donc une sorte de test-and-set, mais j'ai besoin d'une sorte de sémaphore pour empêcher les autres machines de provoquer des conditions de course. Il m'est déjà arrivé qu'un client distant soit créé deux fois pour un seul client local, ce qui n'est pas vraiment souhaitable.

Les solutions que j'ai envisagées sont les suivantes :

  1. Utilisation de notre système de fichiers partagés tolérant aux pannes pour créer des fichiers "verrouillés" qui seront vérifiés par chaque machine en fonction du client.

  2. Utiliser une table spéciale dans notre base de données, et verrouiller toute la table afin de faire un "test-and-set" pour un enregistrement de verrouillage.

  3. Utilisation de Terracotta, un logiciel de serveur à source ouverte qui aide à la mise à l'échelle, mais qui utilise un modèle en étoile.

  4. J'utilise EHCache pour la réplication synchrone de mes "verrous" en mémoire.

Je ne peux pas imaginer que je suis la seule personne à avoir eu ce genre de problème. Comment l'avez-vous résolu ? Avez-vous conçu quelque chose en interne ou avez-vous un produit tiers préféré ?

34voto

Vous pouvez envisager d'utiliser Hazelcast les serrures distribuées. Super léger et facile.

java.util.concurrent.locks.Lock lock = Hazelcast.getLock ("mymonitor");
lock.lock ();
try {
// do your stuff
}finally {
   lock.unlock();
}

Hazelcast - File d'attente distribuée, Map, Set, List, Lock

13voto

fern Points 121

Nous utilisons Terracotta, donc je voudrais voter pour cela.

J'ai suivi Hazelcast et il semble qu'il s'agisse d'une autre technologie prometteuse, mais je ne peux pas voter pour elle car je ne l'ai pas utilisée, et sachant qu'elle utilise un système basé sur le P2P à son audition, je ne lui ferais vraiment pas confiance pour des besoins de grande échelle.

Mais j'ai aussi entendu parler de Zookeeper, qui vient de Yahoo, et qui passe sous l'égide d'Hadoop. Si vous avez envie d'essayer une nouvelle technologie, celle-ci est vraiment très prometteuse car elle est très légère et méchante, et se concentre uniquement sur la coordination. J'aime la vision et la promesse, bien qu'elle soit peut-être encore trop verte.

4voto

Taylor Gautier Points 2044

Terracotta est plus proche d'un modèle "étagé" : toutes les applications clientes communiquent avec un réseau de serveurs Terracotta (et, ce qui est plus important pour l'échelle, elles ne communiquent pas entre elles). La matrice de serveurs Terracotta peut être mise en cluster pour des raisons d'échelle et de disponibilité (en miroir, pour la disponibilité, et en bandes, pour l'échelle).

Quoi qu'il en soit, comme vous le savez probablement, Terracotta vous donne la possibilité d'exprimer la concurrence à travers le cluster de la même manière que vous le faites dans une seule JVM en utilisant les POJO synchronisés/wait/notify ou en utilisant l'une des primitives java.util.concurrentes telles que ReentrantReadWriteLock, CyclicBarrier, AtomicLong, FutureTask et ainsi de suite.

Il existe un grand nombre de recettes simples démontrant l'utilisation de ces primitives dans l'ouvrage Livre de cuisine en terre cuite .

À titre d'exemple, je vais afficher l'exemple ReentrantReadWriteLock (notez qu'il n'y a pas de version "Terracotta" du verrou - vous utilisez simplement le ReentrantReadWriteLock normal de Java)

import java.util.concurrent.locks.*;

public class Main
{
    public static final Main instance = new Main();
    private int counter = 0;
    private ReentrantReadWriteLock rwl = new ReentrantReadWriteLock(true);

    public void read()
    {
        while (true) {
            rwl.readLock().lock();
                try {
                System.out.println("Counter is " + counter);
            } finally {
                rwl.readLock().unlock();
            }
            try { Thread.currentThread().sleep(1000); } catch (InterruptedException ie) {  }
        }
    }

    public void write()
    {
        while (true) {
            rwl.writeLock().lock();
            try {
               counter++;
               System.out.println("Incrementing counter.  Counter is " + counter);
            } finally {
                 rwl.writeLock().unlock();
            }
            try { Thread.currentThread().sleep(3000); } catch (InterruptedException ie) {  }
        }
    }

    public static void main(String[] args)
    {
        if (args.length > 0)  {
            // args --> Writer
            instance.write();
        } else {
            // no args --> Reader
            instance.read();
        }
    }
}

3voto

Nikita Koksharov Points 1552

Je recommande d'utiliser Redisson . Il met en œuvre plus de 30 structures et services de données distribuées, notamment java.util.Lock . Exemple d'utilisation :

Config config = new Config();
config.addAddress("some.server.com:8291");
Redisson redisson = Redisson.create(config);

Lock lock = redisson.getLock("anyLock");
lock.lock();
try {
    ...
} finally {
   lock.unlock();
}

redisson.shutdown();

2voto

Javier Points 33134

J'avais l'intention de conseiller l'utilisation de memcached comme stockage RAM distribué très rapide pour conserver les journaux, mais il semble que EHCache soit un projet similaire, mais plus axé sur Java.

L'un ou l'autre est la solution, tant que vous êtes sûr d'utiliser des mises à jour atomiques (memcached les supporte, je ne sais pas pour EHCache). C'est de loin la solution la plus évolutive.

À titre d'information, Google utilise "Chubby", un système de verrouillage distribué, rapide et basé sur la RAM, comme base de plusieurs systèmes, dont BigTable.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X