Transacción distribuida (Seata)

1. Asuntos

En primer lugar, hablemos de transacciones. Todo el mundo está familiarizado con ellas. Una transacción significa que múltiples adiciones, eliminaciones y cambios de SQL en la base de datos tienen éxito o fallan juntos.
Inserte la descripción de la imagen aquí
Como se muestra arriba: Por ejemplo, cuando hacemos un pedido, el módulo de pedidos, el módulo de inventario y el módulo de cuenta están usando la misma base de datos y la misma base de datos Connect. Sobre esta base, para guardar pedidos, reducir el inventario y reducir los saldos de las cuentas , entonces se puede garantizar que la misma transacción puede garantizar la consistencia de la transacción.

Nota: El énfasis aquí está en la misma base de datos Connect. Si la figura anterior usa la misma base de datos pero no la misma Connect (una Connect para pedidos, una Connect para inventario y una Connect para cuenta), no puede pertenecer a la misma transacción .
 
Resumen: La transacción pertenece a la misma base de datos Connect.

2. Transacciones distribuidas

Al principio, las tres empresas de la imagen anterior pueden pertenecer al mismo proyecto, pero a medida que aumenta el volumen de negocios y aumenta la cantidad de usuarios, es probable que transforme su sistema y es probable que se transforme en lo siguiente:
Inserte la descripción de la imagen aquí
los pedidos, el inventario y la cuenta se dividen en un servicio independiente y cada uno tiene su propia base de datos.

Para un usuario de comercio electrónico, es posible que no sienta ningún cambio y realice un pedido como de costumbre, pero para nuestro personal interno de back-end, el siguiente pedido ahora es muy diferente al anterior, y el sistema de inventario solo puede tener conexiones A Connect a su propia base de datos. Si desea manipular el saldo de la cuenta, solo puede enviar una solicitud desde el sistema de pedidos para operar nuestro sistema de cuenta solo.

En este momento, aún desea garantizar la coherencia de la transacción, ¿qué debe hacer? Aún usa LocalTransactional (transacción local de base de datos) no puede resolver este problema;
entonces usaremos nuestra transacción distribuida en este momento .

3. Caso

Por ejemplo, hay dos servicios: servidor1, servidor2, y las transacciones se agregan a ambos métodos de servicio.

En el servidor1, guardaremos una parte de los datos del servidor1 en la base de datos, y luego llamaremos al servidor2, y el servidor también guardará una parte de los datos del servidor2 en la base de datos. Después de llamar al servidor2, inmediatamente después del servidor1, habrá una excepción. esta vez, habrá varios datos del artículo? ¿De quién son los datos?

Servidor 1:

public class Server1 {
    
    
    
    @Transactional
    public void test() {
    
    
        Server1Dao.insert(new Order(UUID.randomUUID()));
        HttpClient.get("http://localhost:8082/server2/test");
        int i = 1/0;
    }
    
}

Servidor2:

public class Server2 {
    
    
    
    @Transactional
    public void test() {
    
    
        Server2Dao.insert(new Order(UUID.randomUUID()));
    }
    
}

Respuesta: Sí, es un dato de server2.

¿Entonces por qué? Obviamente agregué transacciones a ambos métodos Esto es lo que dijimos, no estamos usando la misma base de datos Connect.
Combinando con la situación real: Mi sistema de pedidos informó un error de reversión, pero mi sistema de inventario aún redujo el inventario y no hubo reversión. Este es un problema muy grande.

Lo que debe hacer la transacción distribuida es: ni siquiera almacenamos datos del servidor2 en la base de datos.

4. Marco de transacciones distribuidas: Seata

En la arquitectura de microservicios, las transacciones distribuidas siempre han sido relativamente difíciles de lograr. Por lo general, no requerimos una gran consistencia y la consistencia final de los datos se logra a través de la cola de mensajes.

Seata es una solución de transacciones distribuidas proporcionada por Ali. A través de Seata, se puede realizar la gestión global de transacciones entre múltiples microservicios.

Seata resuelve el problema de las transacciones distribuidas, con dos intenciones de diseño originales

  • Sin intrusión en el negocio: es decir, para reducir la intrusión de problemas de transacciones distribuidas en el negocio causados ​​por los
    microservicios en la arquitectura técnica. Alto rendimiento: reduce el consumo de rendimiento causado por la solución de transacciones distribuidas . Hay dos implementaciones de transacciones distribuidas en seata Solution, AT y TCC
  • Modo AT : se centra principalmente en la coherencia de datos del acceso a múltiples bases de datos, por supuesto, también incluye el problema de la coherencia de acceso a datos de múltiples bases de datos en múltiples servicios; modo TCC : se centra principalmente en la división del negocio y resuelve la llamada entre microservicios cuando los recursos se expanden horizontalmente de acuerdo con el problema de consistencia empresarial

Seata se divide en tres roles:

TC: Coordinador de transacciones, utilizado para controlar transacciones globales y lotes

TM: Administrador de transacciones, utilizado para iniciar, revertir y confirmar transacciones

RM: Administrador de recursos, utilizado para registrar recursos locales como un lote de transacciones globales.
Inserte la descripción de la imagen aquí

como muestra la imagen:

Las tres transacciones de pedido, inventario y cuenta pertenecen todas a una transacción distribuida. Puede entender TC como una gran transacción. Los pedidos, el inventario y las cuentas son subtransacciones de TC, que se utilizan para coordinar las subtransacciones, ya sea de confirmación o de reversión;

Pero tenga en cuenta: TC es solo para la coordinación. Las operaciones de compromiso y reversión de subtransacciones específicas todavía son operadas por TM. TC solo les dice a estas subtransacciones qué hacer.

5. Ideas de implementación del marco de transacciones distribuidas

Piénselo, si queremos escribir un marco de transacciones distribuidas, ¿cómo deberíamos implementarlo?

En primer lugar: nuestro proceso anterior: ya sea un pedido o un sistema de inventario:

  1. establecer conexión
  2. Transacción abierta
  3. Método de ejecución
  4. Enviar / deshacer
    Inserte la descripción de la imagen aquí
    Obviamente, esto no es suficiente. Debido a que nuestro próximo sistema se envía directamente después de la ejecución, no sabemos si el sistema anterior tuvo éxito o falló.

Entonces, ¿qué debemos hacer para resolver este problema?

Primero : Después de realizar el tercer paso y antes del cuarto paso, esperemos un rato y esperemos a que alguien me diga si debemos comprometernos o retroceder.

1. espera ...

cual es:

  1. establecer conexión
  2. Transacción abierta
  3. Método de ejecución
    // espera ...
  4. Confirmar / deshacer

Segundo : en nuestro caso, ahora hay dos sistemas en la cadena de llamadas, y la orden puede indicar el éxito o el fracaso del sistema de inventario en conjunto. ¿No sería muy complicado si hay cientos de servicios en la cadena de llamadas?

Entonces habrá un administrador de transacciones en este momento , y ahora lo llamamos administrador de transacciones.

Nuestro sistema de pedidos e inventario registra nuestros asuntos ante el gerente de asuntos.

Hay dos parámetros al registrarse:
type: commit / rollBack
porque cuando estamos esperando, realmente sabemos si nuestro método está comprometido o revertido;
groupId: a qué grupo pertenece la transacción.

Inserte la descripción de la imagen aquí

2. Obtenga el control de la transacción, controle el compromiso / retroceso

Tercero : Ahora nuestro administrador de transacciones puede juzgar realmente si nuestra transacción distribuida debe comprometerse / rollBack según el estado de cada subtransacción.

Entonces, al final:
3. Díganos la última operación de la subtransacción: confirmar / deshacer

Inserte la descripción de la imagen aquí

La idea general es así ...

La idea básica de Seata es así ...

6. Pérdidas y ganancias de la arquitectura Seata

6.1 Aspectos destacados
En comparación con otros marcos de transacciones distribuidos, los principales aspectos destacados de la arquitectura Seata son los siguientes:

La capa de aplicación realiza compensación automática basada en análisis SQL, minimizando así la intrusión comercial ;
implementa TC (coordinador de transacciones) de forma independiente en transacciones distribuidas, responsable del registro y reversión de transacciones;
realiza aislamiento de escritura y lectura a través del aislamiento de bloqueos globales.

Hay otros marcos de transacciones distribuidos: TCC, ICN ...
pero el marco de TCC es intrusivo, mientras que Seata no lo es.

Los mecanismos de implementación específicos de estas características se describen en detalle en el sitio web oficial y en github, por lo que no los presentaré aquí.

6.2 Pérdida de rendimiento
Veamos qué gastos generales ha agregado Seata (ignorando cálculos incorrectos para las operaciones de almacenamiento de memoria):
una actualización de SQL requiere la adquisición de xid de transacción global (comunicación con TC), antes de la imagen (analizar SQL, consultar la base de datos una vez), después de la imagen (consulta la base de datos una vez), inserte el registro de deshacer (escriba la base de datos una vez), antes de confirmar (comunicación con TC, determinar el conflicto de bloqueo), todas estas operaciones requieren una comunicación remota RPC y están sincronizadas. Además, el rendimiento de inserción del campo de blob no es alto cuando se escribe el registro de deshacer. Cada SQL de escritura aumentará tanto la sobrecarga, una estimación aproximada aumentaría cinco veces el tiempo de respuesta (aunque asincrónico de dos fases, pero de hecho ocupará recursos del sistema, red, subproceso, base de datos).

¿Cómo generar retrovisores delanteros y traseros? Analice SQL a través de druid, reutilice la condición where en el SQL comercial y luego genere Select SQL para su ejecución.

Supongo que te gusta

Origin blog.csdn.net/RookiexiaoMu_a/article/details/105342614
Recomendado
Clasificación