java postgresql hibernate jpa replication

java - Lectura/escritura de hibernación de división



postgresql hibernate (3)

Deberías:

  1. un DataSource configurado para conectarse al nodo maestro
  2. un DataSource configurado para conectarse al nodo esclavo
  3. el DataSource de enrutamiento se encuentra frente a estos dos, siendo el que usa SessionFactory.
  4. puede usar el indicador @Transactional (readOnly = true) para asegurarse de que enruta las transacciones de solo lectura al DataSource esclavo.
  5. Tanto el DataSource maestro como el esclavo requieren un mecanismo de agrupación de conexiones, y el más rápido es definitivamente HikariCP . HikariCP es tan rápido, que en una de mis pruebas obtuve un tiempo promedio de adquisición de 100us.
  6. Debe asegurarse de establecer el tamaño correcto para sus grupos de conexión, ya que eso puede hacer una gran diferencia. Para esto recomiendo usar flexy-pool . Puedes encontrar más sobre esto here y here .
  7. Debe ser muy diligente y asegurarse de marcar todas las transacciones de solo lectura en consecuencia. Es inusual que solo el 10% de sus transacciones sean de solo lectura. ¿Podría ser que tiene una aplicación de escritura máxima o está utilizando transacciones de escritura en las que solo emite extractos de consulta?
  8. Supervise todas las ejecuciones de consultas utilizando un marco de registro de SQL . Cuanto más corta sea la ejecución de la consulta, más cortos serán los tiempos de adquisición del bloqueo, más transacciones por segundo se acomodarán a su sistema.
  9. Para el procesamiento por lotes definitivamente necesita transacciones de escritura, pero OLTP en general y Hibernate en particular no son la mejor opción para OLAP. Si aún decide utilizar Hibernate para sus trabajos de cuarzo, asegúrese de habilitar el procesamiento por lotes de JDBC y debe tener estas propiedades de Hibernate establecidas:

    <property name="hibernate.order_updates" value="true"/> <property name="hibernate.order_inserts" value="true"/> <property name="hibernate.jdbc.batch_versioned_data" value="true"/> <property name="hibernate.jdbc.fetch_size" value="25"/> <property name="hibernate.jdbc.batch_size" value="25"/>

Para el procesamiento por lotes, puede usar una fuente de datos separada que use un grupo de conexiones diferente (y como ya dijo que tiene una JVM diferente, eso es lo que ya tiene). Solo asegúrese de que el tamaño total de la conexión de todos los grupos de conexiones sea menor que la cantidad de conexiones con las que PostgreSQL se ha configurado.

Así que el procesador por lotes usa un HikariCPDataSource separado que se conecta al maestro. Cada trabajo por lotes debe usar una transacción dedicada, así que asegúrese de usar un tamaño de lote razonable. Desea mantener los bloqueos y terminar las transacciones lo más rápido posible. Si el procesador por lotes utiliza trabajadores de procesamiento concurrente, asegúrese de que el tamaño del grupo de conexiones asociado sea igual al número de trabajadores, de modo que no esperen a que otros liberen las conexiones.

Tengo una aplicación web java bastante pesada que atiende a miles de solicitudes por segundo y utiliza una base de datos maestra de Postgresql que se replica a sí misma en una base de datos secundaria (solo lectura) mediante replicación de transmisión (asíncrona).

Por lo tanto, separo la solicitud de primaria a secundaria (solo lectura) mediante URL para evitar llamadas de solo lectura a la base de datos primaria de errores, considerando que el tiempo de replicación es mínimo.

NOTA : uso una sessionFactory con un RoutingDataSource provisto por spring que busca db para usar en base a una clave. Estoy interesado en la multitenencia, ya que estoy usando hibernate 4.3.4 que lo admite.

Tengo dos preguntas:

  1. No creo que dividir en base a las URL sea eficiente, ya que solo puedo mover el 10% del tráfico, lo que significa que no hay muchas URL de solo lectura. ¿Qué enfoque debo considerar?
  2. Puede ser, de alguna manera, sobre la base de las URL que alcance un cierto nivel de distribución entre ambos nodos, pero ¿qué haría con mis trabajos de cuarzo (que incluso tienen JVM por separado)? ¿Qué enfoque pragmático debo tomar?

Sé que podría no obtener una respuesta perfecta ya que esto es realmente amplio, pero solo quiero tu opinión para el contexto.

Dudes que tengo en mi equipo:

  • Primavera 4
  • Hibernate4
  • Cuarzo2.2
  • Java7 / Tomcat7

Por favor tome interés. Gracias por adelantado.


Si entiendo correctamente, el 90% de las solicitudes HTTP a su aplicación web involucran al menos una escritura y tienen que operar en la base de datos maestra. Puede dirigir las transacciones de solo lectura a la base de datos de copia, pero la mejora solo afectará al 10% de la operación de las bases de datos globales e incluso esas operaciones de solo lectura llegarán a una base de datos.

La arquitectura común aquí es utilizar un buen caché de base de datos (Infinispan o Ehcache). Si puede ofrecer un caché lo suficientemente grande, puede esperar que una buena parte de la base de datos solo lea el caché y se convierta en operaciones de solo memoria, ya sea que forme parte de una transacción de solo lectura o no. El ajuste de caché es una operación delicada, pero en mi humilde opinión es necesario para lograr una alta ganancia de rendimiento. Esos cachés incluso permiten la distribución de front -ends, incluso si la configuración es un poco más difícil en ese caso (es posible que tenga que buscar clústeres de terracota si desea utilizar Ehcache).

Actualmente, la replicación de la base de datos se usa principalmente para proteger los datos, y se usa como un mecanismo de mejora de la concurrencia solo si tiene partes altas de los Sistemas de información que solo leen datos, y no es lo que está describiendo.


Usted está diciendo que las URL de su aplicación solo tienen un 10% de lectura, por lo que el otro 90% tiene al menos algún tipo de escritura en la base de datos.

10% LEER

Puede pensar en usar un diseño CQRS que pueda mejorar el rendimiento de lectura de su base de datos. Sin duda, se puede leer desde la base de datos secundaria y, posiblemente, se puede hacer más eficiente diseñando las consultas y los modelos de dominio específicamente para la capa de lectura / vista.

No ha dicho si las solicitudes del 10% son caras o no (por ejemplo, informes en ejecución)

Preferiría usar un sessionFactory separado si siguiera el diseño de CQRS ya que los objetos que se cargan / almacenan en caché probablemente sean diferentes a los que se escriben.

90% ESCRIBIR

En lo que respecta al 90% restante, no querrá leer desde la base de datos secundaria (mientras escribe en la primaria) durante alguna lógica de escritura, ya que no querrá tener datos potencialmente obsoletos.

Es probable que algunas de estas lecturas estén buscando datos "estáticos". Si el almacenamiento en caché de Hibernate no reduce los aciertos de la base de datos para las lecturas, consideraría un caché en memoria como Memcached o Redis para este tipo de datos. Este mismo caché podría ser utilizado tanto por el 10% de lectura como por el 90% de los procesos de escritura.

Para las lecturas que no son estáticas (es decir, la lectura de datos que ha escrito recientemente), Hibernate debe contener los datos en su caché de objetos si tiene el tamaño adecuado. ¿Puede determinar el rendimiento de su caché de éxito / falta?

CUARZO

Si está seguro de que un trabajo programado no afectará al mismo conjunto de datos que otro trabajo, puede ejecutarlos en diferentes bases de datos, sin embargo, si tiene dudas, siempre realice actualizaciones por lotes en un servidor (principal) y replique los cambios. Es mejor ser lógicamente correcto, que introducir problemas de replicación.

DB PARTICIONANDO

Si sus 1,000 solicitudes por segundo están escribiendo una gran cantidad de datos, observe la partitioning su base de datos. Usted puede encontrar que tiene mesas cada vez mayor. La partición es una forma de abordar esto sin archivar datos.

A veces necesitas poco o ningún cambio en el código de tu aplicación.

Archivar es obviamente otra opción.

Descargo de responsabilidad: Cualquier pregunta como esta siempre será específica de la aplicación. Siempre trata de mantener tu arquitectura lo más simple posible.