Pregunta

He estado trabajando en esto por un par de días, y he encontrado varias soluciones pero ninguna de ellas increíblemente simple o ligero.El problema es básicamente esto:Tenemos un grupo de 10 máquinas, cada una de las cuales se ejecuta el mismo programa en un multiproceso ESB plataforma.Puedo lidiar con los problemas de concurrencia entre los hilos en la misma máquina con bastante facilidad, pero ¿qué acerca de la concurrencia en los mismos datos en diferentes máquinas?

Esencialmente, el software recibe solicitudes para alimentar a un cliente de los datos de un negocio a otro a través de servicios web.Sin embargo, el cliente puede o no puede existir sin embargo, en el otro sistema.Si no lo hace, nosotros lo creamos a través de un método de servicio web.Por lo que se requiere una especie de test-and-set, pero necesito un semáforo de algún tipo de bloqueo de las otras máquinas de causar condiciones de carrera.He tenido situaciones de antes, donde un cliente remoto se creó dos veces para un solo cliente local, que en realidad no es deseable.

Soluciones que he jugado con conceptualmente son:

  1. El uso de nuestra tolerancia a errores del sistema de archivos compartidos para crear el "bloqueo" de los archivos que van a ser comprobados por cada máquina en función del cliente

  2. Usando una tabla especial en nuestra base de datos, y el bloqueo de toda la tabla con el fin de hacer un "test-and-set" para un bloqueo de registro.

  3. El uso de Terracota, una fuente abierta de software de servidor que ayuda en la ampliación, sino que utiliza un hub-and-spoke modelo.

  4. El uso de EHCache para la replicación sincrónica de mi memoria "bloquea."

No me puedo imaginar que yo soy la única persona que ha tenido alguna vez este tipo de problema.¿Cómo resolverlo?¿Cocinar algo en casa o ¿tiene un favorito de la 3º parte del producto?

¿Fue útil?

Solución

usted puede ser que desee considerar el uso de Hazelcast distribuido bloqueos.Super lite y fácil.

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

Hazelcast Distribuidos De La Cola, Mapa, Conjunto, Lista De Bloqueo

Otros consejos

Utilizamos Terracota, así que me gustaría votar por eso.

He estado siguiendo Hazelcast y parece otra tecnología prometedora, pero no pueden votar por él, ya que no he usado, y sabiendo que utiliza un P2P sistema basado en su oído, yo realmente no podría confiar en él para la gran escala de las necesidades.

Pero también he oído hablar de Cuidador, que salió de Yahoo, y se mueve bajo la Hadoop paraguas.Si eres aventurero probar algunas de las nuevas tecnología de esto realmente tiene un montón de promesa, ya que es muy magra y media, centrando los esfuerzos en la coordinación.Me gusta la visión y la promesa, aunque puede ser demasiado verde todavía.

Terracota está más cerca de una "niveles" modelo - todas las aplicaciones de cliente de hablar con una de Terracota de la Matriz de Servidor (y lo que es más importante para la escala no hablan el uno al otro).La Terracota Matriz de Servidor es capaz de ser agrupado para la escala y la disponibilidad (la inversa, para la disponibilidad, y de rayas, para la escala).

En cualquier caso, como usted probablemente sabe de Terracota le da la capacidad para expresar la simultaneidad de todo el grupo, de la misma manera que en una sola JVM mediante el uso de POJO sincronizado/esperar/notificar o mediante cualquiera de los de java.util.concurrente primitivas como ReentrantReadWriteLock, CyclicBarrier, AtomicLong, FutureTask y así sucesivamente.

Hay un montón de recetas sencillas que demuestran el uso de estos primitivos en la Terracota Libro De Cocina.

Como ejemplo, voy a publicar el ReentrantReadWriteLock ejemplo (nota: no hay ningún "Terracota", versión de la cerradura - sólo uso normal de Java ReentrantReadWriteLock)

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();
        }
    }
}

Recomiendo el uso de Redisson.Se implementa más de 30 distribuido estructuras de datos y servicios, incluyendo java.util.Lock.Ejemplo de uso:

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();

Yo iba a asesoramiento en el uso de memcached como muy rápido, distribuidos de la RAM de almacenamiento para mantener los registros;pero parece que EHCache es un proyecto similar, pero más centrado en java.

Uno es el camino a seguir, siempre y cuando estés seguro de que el uso de las actualizaciones atómicas (memcached apoya, no sé acerca de EHCache).Es por lejos la solución más escalable.

Como un punto de datos, Google utiliza 'Gordito', una forma rápida, basada en RAM distribuida de bloqueo de almacenamiento como la raíz de varios sistemas, entre ellos BigTable.

He hecho un montón de trabajo con Coherencia, lo que permitió a varios enfoques para la realización de un bloqueo distribuida.El enfoque ingenuo fue a petición de bloquear el mismo objeto lógico en todos los nodos participantes.En Coherencia términos este fue el bloqueo de una clave en una Replica de la Caché.Este enfoque no escala bien porque el tráfico de la red aumenta linealmente a medida que agregar nodos.Una forma más inteligente fue el uso de una Caché Distribuida, donde cada nodo en el clúster es, naturalmente, responsable de una porción del espacio de claves, por lo que el bloqueo de una clave en un caché siempre involucradas en la comunicación con más de un nodo.Usted podría desarrollar su propio enfoque basado en esta idea, o mejor aún, conseguir la Coherencia.Lo que realmente es la escalabilidad toolkit de sus sueños.

Me gustaría añadir que cualquier medio decente multi-nodo de la red basado en el mecanismo de bloqueo tendría que ser razonablemente sofisticada para actuar correctamente en caso de fallo de la red.

No estoy seguro si entiendo todo el contexto, pero suena como que tiene 1 sola base de datos de copia de esto?¿Por qué no hacer uso de la base de datos del bloqueo:si la creación de la cliente es una sola INSERTAR, a continuación, esta declaración solo puede servir como un bloqueo desde la base de datos va a rechazar una segunda INSERCIÓN que viola uno de sus limitaciones (por ejemplo,el hecho de que el nombre del cliente es único, por ejemplo).

Si la "inserción de un cliente de la operación" no es atómico y es un lote de instrucciones, a continuación, me gustaría introducir (o uso) una primera INSERCIÓN que crea algunos simple registro básico la identificación de su cliente (con la necesaria Singularidad restricciones) y, a continuación, hacer todas las inserciones y actualizaciones en la misma transacción.De nuevo la base de datos se encargará de consistencia y cualquier concurrente modificaciones resultará en uno de ellos falla.

He hecho una simple RMI servicio con dos métodos:bloqueo y la liberación.ambos métodos toman una clave (mi modelo de datos utilizado Uuid como pk por lo que fue también la llave de bloqueo).

RMI es una buena solución para esto porque es centralizado.usted no puede hacer esto con los Ejb (specialially en un clúster como usted no sabe la máquina en la que su llamada de la tierra).además, es muy fácil.

a mí me funcionó.

Si usted puede configurar el equilibrio de carga de modo que las solicitudes para un solo cliente siempre se correlacionan con el mismo servidor, a continuación, usted puede manejar esto a través de la sincronización local.Por ejemplo, tome su ID de cliente mod 10 a encontrar que de los 10 nodos a utilizar.

Incluso si usted no quiere hacer esto en el caso general, los nodos podría proxy para cada uno de los otros para este tipo de solicitud.

Suponiendo que sus usuarios son uniformes suficiente (es decir,si usted tiene un montón de ellos), que no esperamos que los puntos calientes de pop-up en donde un nodo se sobrecarga, este debe todavía escala bastante bien.

Usted también podría considerar la posibilidad Cacheonix de distribución de los bloqueos.A diferencia de cualquier otra cosa que se mencionan aquí Cacheonix apoyo ReadWrite cerraduras con la extensión de bloqueo de leer a escribir cuando sea necesario:

ReadWriteLock rwLock = Cacheonix.getInstance().getCluster().getReadWriteLock();
Lock lock = rwLock.getWriteLock();
try {
  ...
} finally {
  lock.unlock();
}

La divulgación completa:Soy un Cacheonix desarrollador.

Puesto que ya se conecta a una base de datos, antes de añadir otro infra pieza, echa un vistazo a JdbcSemaphore, es fácil de usar:

JdbcSemaphore semaphore = new JdbcSemaphore(ds, semName, maxReservations);
boolean acq = semaphore.acquire(acquire, 1, TimeUnit.MINUTES);
if (acq) {
 // do stuff
 semaphore.release();
} else {
  throw new TimeoutException();
}

Es parte de spf4j biblioteca.

De vuelta en el día, tendríamos que usar una específica "de bloqueo del servidor" en la red para manejar esto.Bleh.

Su servidor de base de datos podría tener recursos específicamente para hacer este tipo de cosas.MS-SQL Server tiene bloqueos de aplicación utilizable a través de la sp_getapplock/sp_releaseapplock procedimientos.

Hemos sido el desarrollo de un código abierto, distribuido de la sincronización de marco, en la actualidad DistributedReentrantLock y DistributedReentrantReadWrite de bloqueo ha sido implementado, pero todavía están en pruebas y refactorización de fase.En nuestra arquitectura de bloqueo de teclas se divide en segmentos y cada nodo es responsable de cierto número de cubos.Tan efectiva para un exitoso solicitudes de bloqueo, sólo hay una solicitud de red.También estamos utilizando AbstractQueuedSynchronizer clase como local en estado de bloqueo, con lo que todo el error de las solicitudes de bloqueo son manejados localmente, esto reduce drásticamente la red de tráfico.Estamos utilizando JGroups (http://jgroups.org) para la comunicación de grupo y de Hess para la serialización.

para más detalles, por favor consulte http://code.google.com/p/vitrit/.

Por favor envíeme su valiosa retroalimentación.

Kamran

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top