java - que - oracle rac balanceamento de carga
Soluciones Java para transacciones distribuidas y/o datos compartidos en clúster (6)
Gracias por resumir todas las posibilidades en un solo lugar.
Sin embargo, falta una técnica aquí. Es MapReduce-Hadoop. Si es posible ajustar el problema en el paradigma MapReduce, es quizás la solución más ampliamente disponible. También me pregunto si el patrón de Actor Framework (JetLang, Kilim, etc.) se puede extender a un clúster.
¿Cuáles son los mejores enfoques para agrupar / distribuir una aplicación de servidor Java? Estoy buscando un enfoque que le permita escalar horizontalmente agregando más servidores de aplicaciones y más servidores de bases de datos.
- ¿Qué tecnologías (técnicas de ingeniería de software o tecnologías específicas) sugeriría para abordar este tipo de problema?
- ¿Qué técnicas utiliza para diseñar una capa de persistencia para escalar a muchos lectores / escritores Escale las transacciones de la aplicación y acceda a los datos compartidos (el mejor enfoque es eliminar los datos compartidos, qué técnicas puede aplicar para eliminar los datos compartidos).
- Parece que se necesitan diferentes enfoques dependiendo de si sus transacciones son leídas o escritas, pero siento que puede optimizar una aplicación pesada de "escritura" que también sería eficiente para "leer"
La "mejor" solución le permitirá escribir una aplicación Java para un solo nodo y con suerte "ocultar" la mayoría de los detalles de acceso / bloqueo de datos compartidos.
En un entorno distribuido, la cuestión más difícil siempre se reduce a tener múltiples transacciones accediendo a datos compartidos. Parece que hay 2 enfoques comunes para las transacciones concurrentes.
- Bloqueos explícitos (que es extremadamente propenso a errores y lento de coordinar a través de múltiples nodos en un sistema distribuido)
- Memoria transaccional de software (STM) También concurrencia optimista de AKA en la que se revierte una transacción durante una confirmación si descubre que el estado compartido ha cambiado (y la transacción puede volverse a intentar más adelante). ¿Qué enfoque escala mejor y cuáles son las compensaciones en un sistema distribuido?
He estado investigando soluciones de escalado (y en aplicaciones generales que proporcionan un ejemplo de cómo escalar) como:
- Terracota : proporciona escalamiento "transparente" extendiendo el modelo de memoria Java para incluir memoria compartida distribuida utilizando el mecanismo de bloqueo de simultaneidad de Java (sincronizado, ReentrantReadWriteLocks).
- Google App Engine Java : le permite escribir aplicaciones Java (o python) que se distribuirán entre servidores "en la nube" donde distribuye el servidor que maneja una transacción y usa BigTable para almacenar sus datos persistentes (no estoy seguro de cómo las transacciones que acceden compartieron datos o manejar conflictos de bloqueo para poder escalar de manera efectiva)
- Darkstar MMO Server : Darkstar es el servidor de juegos de código abierto MMO (multijugador masivo en línea) de Sun que escala las transacciones de una manera transaccional, lo que permite que una transacción determinada solo se ejecute por una cierta cantidad y compromiso, y si demora, se revertirá (algo así como memoria transaccional de software). Han estado investigando para admitir una configuración de servidor de varios nodos para escalar.
- Bloqueo optimista de Hibernate : si está utilizando Hibernate, puede usar su compatibilidad de simultaneidad optimista para admitir el comportamiento del tipo de memoria transaccional del software
- Apache CouchDB se supone que debe "escalar" a muchos DB lectores / escritores en una configuración de malla, naturalmente. (¿Hay un buen ejemplo de cómo administra los datos de bloqueo o asegura el aislamiento de la transacción?):
- JCache : amplíe las aplicaciones pesadas de "lectura" almacenando en el caché los resultados de consultas comunes que puede usar en Google appengine para acceder a memcached y almacenar en caché otros datos que se leen con frecuencia.
Terracotta parece ser la solución más completa, ya que puede "modificar" fácilmente una aplicación de servidor existente para admitir el escalado (después de definir los objetos @Root y los métodos @ AutoLockRead / Write). El problema es obtener el máximo rendimiento de una aplicación distribuida, la optimización para sistemas distribuidos no es realmente una idea de que uno tiene que diseñarlo sabiendo que el acceso a objetos podría bloquearse con la E / S de red.
Para escalar correctamente, parece que siempre se reduce a dividir datos y realizar transacciones de equilibrio de carga de modo tal que una "unidad de ejecución" determinada (núcleo de CPU -> hilo -> nodo de aplicación distribuida -> nodo maestro de DB)
Sin embargo, parece que para hacer que cualquier escala de aplicación sea adecuada al agrupar, debe poder realizar una partición de sus transacciones en términos de sus lecturas / escrituras de acceso a datos. ¿Qué soluciones tiene la gente para distribuir sus datos de aplicaciones (Oracle, Google BigTable, MySQL, almacenamiento de datos) y, en general, cómo gestiona los datos de particiones (muchos maestros de escritura, con muchos más datos de lectura, etc.).
En términos de escalamiento de la capa de persistencia de datos, qué tipo de configuración escalará mejor en términos de particionar sus datos a muchos lectores / muchos escritores (generalmente dividiría mis datos en función de un usuario dado (o cualquier entidad central que generalmente sea su entidad de objeto "raíz") que es propiedad de un solo DB maestro
No te olvides de la Mnesia de Erlang.
Mnesia le ofrece cosas como transacciones a las que está acostumbrado en una base de datos normal, pero proporciona operaciones en tiempo real y tolerancia a fallas. Además, puede reconfigurar cosas sin tiempo de inactividad. Lo malo es que es una base de datos residente en memoria, por lo que debe fragmentar tablas realmente grandes. El tamaño de la mesa más grande es 4Gb.
- No te olvides de Coherence y GigaSpaces .
Tal vez esas diapositivas serán útiles. Desde nuestra experiencia, recomendaría Oracle (Tangosol) Coherence y GigaSpaces como los marcos de distribución de datos y procesamiento más potentes que existen. Dependiendo de la naturaleza exacta del problema, uno de ellos puede brillar. Terracota también es bastante aplicable para algunos de los problemas.
Pensé que había encontrado una gran plataforma Java Clustering / Distributed, quería reabrir esta-
Pago y envío http://www.hazelcast.com
Ejecuté los programas de prueba, es muy bueno, muy ligero y fácil de usar. Detecta automáticamente los miembros del clúster en una configuración de igual a igual. Las oportunidades son ilimitadas.
Si bien Oracle Coherence y muchas de las otras soluciones sugeridas son buenas para compartir datos, solo mencionó el bloqueo y STM como formas de administrar la mutación de estado en un entorno distribuido; esas son, en general, formas bastante pobres de escalar la gestión estatal. En un sitio diferente, recientemente publiqué lo siguiente sobre cómo implementar (por ejemplo) contadores de secuencia:
Si está buscando un contador, entonces usar algo así como un procesador de entrada Coherence logrará fácilmente el comportamiento "una vez y solo una vez" y HA para cualquier número de secuencias monótonamente crecientes; aquí está toda la implementación:
public class SequenceCounterProcessor
extends AbstractProcessor
{
public Object process(InvocableMap.Entry entry)
{
long l = entry.isPresent() ? (Long) entry.getValue() + 1 : 0;
entry.setValue(l);
return l;
}
}
Sip. Eso es. HA automático e ininterrumpido, elasticidad de escalamiento dinámico, comportamiento de una vez y solo una vez, etc. Hecho.
El EntryProcessor es un tipo de cierre distribuido que presentamos en 2005.
Como un aparte, en Java 8 (aún no lanzamiento), el proyecto Lambda presenta soporte de cierre oficial en el lenguaje y las bibliotecas estándar.
Básicamente, la idea es entregar el cierre a la ubicación del "propietario" de los datos en un entorno distribuido. Coherence gestiona dinámicamente la propiedad de los datos mediante el uso de particiones dinámicas, lo que permite que el sistema distribuido equilibre la carga de datos entre las diversas máquinas y nodos que se están ejecutando. De hecho, de manera predeterminada, todo esto está 100% automatizado, por lo que nunca le dice dónde colocar los datos, ni la cantidad de datos. Además, hay copias secundarias (y tal vez terciarias, etc.) de los datos administrados en otros nodos y otros servidores físicos, para proporcionar una alta disponibilidad en caso de que un proceso falle o muera un servidor. De nuevo, la gestión de estas copias de seguridad es completamente automática y completamente sincrónica por defecto, lo que significa que el sistema es 100% HA por defecto (es decir, sin configuración).
Cuando el cierre llega al propietario de los datos, se ejecuta en un espacio de trabajo transaccional, y si la operación se completa con éxito, se envía a la copia de seguridad para su custodia. La mutación de datos (por ejemplo, el resultado de la operación) solo se hace visible para el resto del sistema una vez que la copia de seguridad se ha realizado con éxito.
Algunas optimizaciones de lo anterior incluyen agregar las interfaces ExternalizableLite y PortableObject para una serialización optimizada, y evitar la serialización del largo encuadrado yendo después de la forma de datos "lista para la red" directamente:
public Object process(InvocableMap.Entry entry)
{
try
{
BinaryEntry binentry = (BinaryEntry) entry;
long l = entry.isPresent() ? binentry.getBinaryValue()
.getBufferInput().readLong() + 1 : 0L;
BinaryWriteBuffer buf = new BinaryWriteBuffer(8);
buf.getBufferOutput().writeLong(l);
binentry.updateBinaryValue(buf.toBinary());
return l;
}
catch (IOException e)
{
throw new RuntimeException(e);
}
}
Y dado que no tiene estado, ¿por qué no tener una instancia de singleton lista para funcionar?
public static final SequenceCounterProcessor INSTANCE =
new SequenceCounterProcessor();
Usarlo desde cualquier lugar de la red es tan simple como una sola línea de código:
long l = (Long) sequences.invoke(x, SequenceCounterProcessor.INSTANCE);
Donde "x" es cualquier objeto o nombre que identifica el contador de secuencia particular que desea utilizar. Para obtener más información, consulte la base de conocimiento de Coherence en: http://coherence.oracle.com/
Oracle Coherence es un sistema distribuido. Cada vez que inicie un nodo de coherencia, se unirá a otros nodos de coherencia que ya se están ejecutando y formará dinámicamente un clúster elástico. Ese clúster aloja datos en una forma particionada, de alta disponibilidad (HA) y transaccionalmente consistente, y operaciones de hosts (como la que mostré arriba) que operan en esos datos "de una vez y solo una vez".
Además, además de la capacidad de invocar cualquiera de esa lógica o acceder a cualquiera de esos datos de forma transparente desde cualquier nodo Coherence, también puede invocar cualquiera de esa lógica o acceder a cualquiera de esos datos de forma transparente desde cualquier proceso en la red (sujeto a autenticación y autorización, por supuesto). Por lo tanto, este código funcionaría desde cualquier nodo del clúster Coherence o desde cualquier cliente (Java / C / C ++ / C # / .NET):
Por el bien de la divulgación completa, trabajo en Oracle. Las opiniones y opiniones expresadas en este post son mías y no reflejan necesariamente las opiniones o opiniones de mi empleador.