springcloudAlibaba --- Componente de transacciones distribuidas Seata

Introducción

Una transacción es una unidad de ejecución de programa que accede y posiblemente actualiza varios elementos de datos en la base de datos. En una base de datos relacional
, una transacción consta de un conjunto de declaraciones SQL. Las transacciones deben tener cuatro atributos: atomicidad, coherencia, aislamiento y durabilidad.
Estas cuatro propiedades a menudo se denominan propiedades ÁCIDAS.
Atomicidad: una transacción es una unidad de trabajo indivisible y todas las operaciones incluidas en la transacción se realizan o no se realizan
.
Consistencia: una transacción debe cambiar la base de datos de un estado de coherencia a otro y
no se puede observar el estado intermedio de la transacción.
Aislamiento: la ejecución de una transacción no puede ser interferida por otras transacciones. Es decir, las operaciones y los datos utilizados dentro de una transacción
están aislados de otras transacciones simultáneas y las transacciones ejecutadas simultáneamente no pueden interferir entre sí. El aislamiento se divide en cuatro niveles: lectura
no confirmada, lectura comprometida (para resolver lecturas sucias), lectura repetible (
lectura repetible, para resolver lecturas fantasmas), serializable (para resolver lecturas fantasmas).
Durabilidad: La durabilidad, también llamada permanencia, significa que una vez que se confirma una transacción, sus
cambios en los datos de la base de datos deben ser permanentes. Las operaciones o fallos posteriores no deberían tener ningún impacto en él.
Al implementar cualquier mecanismo de transacción, se deben considerar las características ACID de las transacciones, incluidas: transacciones locales y transacciones distribuidas. Si no pueden
satisfacerse completamente a tiempo, también se debe considerar hasta qué punto pueden ser respaldadas.

Transacción local
@Transational
En la mayoría de los escenarios, nuestra aplicación solo necesita operar una única base de datos. La transacción en este caso se denomina transacción local
(Transacción local). Las propiedades ACID de las transacciones locales están respaldadas directamente por la base de datos. La arquitectura de la aplicación de transacciones locales es la siguiente
:
en la programación JDBC, utilizamos el objeto java.sql.Connection para abrir, cerrar o enviar transacciones. El código se ve así
:

1 Connection conn = ... //获取数据库连接
2 conn.setAutoCommit(false); //开启事务
3 try{
    
    
4    //...执行增删改查sql
5    conn.commit(); //提交事务
6 }catch (Exception e) {
    
    
7   conn.rollback();//事务回滚
8 }finally{
    
    
9    conn.close();//关闭链接
10 }

Escenarios típicos de transacciones distribuidas.

En la actualidad, el desarrollo de Internet está en pleno apogeo y la mayoría de las empresas han realizado la división de bases de datos y la orientación a servicios (SOA). En este caso, completar una determinada función empresarial puede requerir operar en múltiples servicios y múltiples bases de datos. Esto implica transacciones distribuidas, donde los recursos que deben operarse están ubicados en múltiples servidores de recursos, y la aplicación debe garantizar que todas las operaciones con datos de múltiples servidores de recursos tengan éxito o fallen. Básicamente, las transacciones distribuidas tienen como objetivo garantizar la coherencia de los datos entre diferentes servidores de recursos.
Escenario típico de transacción distribuida:
transacción entre bases de datos
La transacción entre bases de datos significa que una determinada función de una aplicación necesita operar varias bibliotecas y diferentes datos comerciales se almacenan en diferentes bibliotecas. El autor ha visto
un negocio relativamente complejo en el que funcionaban 9 bibliotecas al mismo tiempo.
Insertar descripción de la imagen aquí
División de bases de datos y tablas
Por lo general, cuando una base de datos tiene un gran volumen de datos o el volumen de datos futuro esperado es relativamente grande, se dividirá horizontalmente, es decir, en bases de datos y tablas. Como se muestra
en la siguiente figura, la base de datos B se divide en 2 bibliotecas:

Para el caso de subbases de datos y subtablas, los desarrolladores generalmente utilizan algún middleware de base de datos para reducir la complejidad de las operaciones SQL. Por ejemplo, para
SQL: inserte en los valores de usuario (id, nombre) (1, "Zhang San"), (2, "Li Si"). Este SQL es la sintaxis para operar una sola base de datos.
En el caso de una sola base de datos, se puede garantizar la coherencia de las transacciones.
Sin embargo, dado que la base de datos y las tablas ahora están divididas en subbases de datos, el desarrollador espera insertar el registro número 1 en la subbase de datos 1 y el registro número 2 en la subbase de datos 2. Por lo tanto, el
middleware de la base de datos necesita reescribirlo en dos declaraciones SQL e insertarlas en dos subbases de datos diferentes respectivamente. En este momento, es necesario garantizar que ambas bibliotecas tengan éxito o
fallen. Por lo tanto, básicamente todo el middleware de la base de datos se enfrenta al problema de transacciones distribuidas.
Insertar descripción de la imagen aquí

La arquitectura de microservicios orientada a servicios
es un concepto relativamente popular en la actualidad. Por ejemplo, en el caso mencionado por el autor anterior, una aplicación opera
9 bibliotecas al mismo tiempo. La lógica de negocios de dicha aplicación debe ser muy compleja, lo cual es un gran desafío para los desarrolladores. Debe dividirse en diferentes
servicios independientes. para simplificar la lógica de negocio. Después de la división, los servicios independientes pueden realizar llamadas remotas a través del marco RPC para comunicarse entre sí. La siguiente figura
muestra una arquitectura en la que tres servicios se llaman entre sí:
el servicio A necesita operar directamente la base de datos para completar una determinada función y necesita llamar al servicio B y al servicio C al mismo tiempo. El servicio B
opera dos bases de datos al mismo tiempo. tiempo, y el Servicio C también opera una biblioteca. Es necesario garantizar que estas operaciones entre servicios en múltiples bases de datos
tengan éxito o fracasen. De hecho, este puede ser el escenario de transacciones distribuidas más típico.

小结:上述讨论的分布式事务场景中,无一例外的都直接或者间接的操作了多个数据库。如何保证事务的ACID特性,对于分布式事务实现方案而言,是非常大的挑战。同时,分布式事务实现方案还必须要考虑性能的问题,如果为了严格保证ACID特性,导致性能严重下降,那么对于一些要求快速响应的业务,是无法接受的。

Insertar descripción de la imagen aquí
Soluciones comunes de transacciones distribuidas
1, marco de transacciones distribuidas de Seata Alibaba
2, cola de mensajes
3, saga
4, XA

Base teórica de las cosas distribuidas.

Actualmente, las principales soluciones de transacciones distribuidas del mercado son todos protocolos de 2PC. Esta es la razón interna por la que entre las soluciones de transacciones distribuidas comunes mencionadas al principio del artículo, todas las enumeradas tienen una cosa en común: "dos etapas". Cuando algunos artículos analizan 2PC, casi siempre usan el ejemplo de dos fases de TCC, la primera fase es intentar y la segunda fase es completar, confirmar o cancelar. De hecho, 2PC no está diseñado específicamente para implementar TCC. 2PC es universal y existe como un protocolo. La mayoría de las soluciones distribuidas actuales se basan en el protocolo de envío de dos fases 2PC. TCC (Try-Confirm-Cancel) es en realidad un protocolo de envío de dos etapas basado en servicios.

Protocolo de confirmación de dos fases de 2PC, dividido en preparación y
preparación de confirmación: las cosas envían solicitudes de transacción
Insertar descripción de la imagen aquí

  1. Solicite al coordinador que envíe una solicitud de transacción a todos los participantes, pregunte si se puede realizar la operación de transacción y luego espere la respuesta de cada participante.
  2. Después de que cada participante recibe la solicitud de transacción del coordinador, realiza operaciones de transacción (como actualizar registros en una tabla de base de datos relacional) y
    registra información de Deshacer y Rehacer en el registro de transacciones.
  3. Respuesta Si el participante ejecuta exitosamente la transacción y escribe información de Deshacer y Rehacer, se devuelve una respuesta SÍ al coordinador; de lo contrario,
    se devuelve una respuesta NO. Por supuesto, el participante también puede estar caído y no se devolverá ninguna respuesta.

Confirmar: ejecutar el envío de la transacción
La ejecución del envío de la transacción se divide en dos situaciones: envío normal y reversión.
Insertar descripción de la imagen aquí

  1. El coordinador de solicitudes de compromiso envía una solicitud de compromiso a todos los participantes.
  2. Después de que el participante del envío de la transacción recibe la solicitud de confirmación, ejecuta el envío de la transacción y libera todos los recursos ocupados durante el período de ejecución de la transacción una vez que se completa el envío.
  3. Después de que el participante del resultado de la retroalimentación ejecuta el envío de la transacción, envía una respuesta Ack al coordinador.
  4. Finalización de la transacción Después de recibir respuestas Ack de todos los participantes, la transacción se completa y confirma.

Interrupción de la transacción
Durante la ejecución del paso Preparar, si algunos participantes no ejecutan la transacción, están inactivos o la red con el coordinador se interrumpe, entonces el coordinador no puede
recibir respuestas SÍ de todos los participantes, o un participante regresa Si un No Se recibe la respuesta, el coordinador ingresará al proceso de reversión y revertirá la transacción
. El proceso es como se muestra en la parte roja de la figura siguiente (reemplace la solicitud de confirmación con la solicitud de reversión roja):
Insertar descripción de la imagen aquí

  1. Solicitud de reversión El coordinador envía una solicitud de reversión a todos los participantes.

  2. Después de que el participante de la reversión de la transacción recibe la reversión, utiliza el registro de deshacer en la fase de preparación para realizar la reversión de la transacción y libera todos los recursos ocupados durante el período de ejecución de la transacción una vez completada .
  3. El participante del resultado de la retroalimentación envía una respuesta Ack al coordinador después de realizar la reversión de la transacción.
  4. Una vez que la transacción interrumpida recibe respuestas Ack de todos los participantes, se completa la interrupción de la transacción.

problema de 2 piezas

  1. Cuando los participantes del bloqueo sincrónico esperan instrucciones del coordinador, en realidad están esperando respuestas de otros participantes. Durante este proceso, los participantes no pueden realizar
    otras operaciones, es decir, su operación se bloquea. Si hay una anomalía en la red entre el participante y el coordinador que impide que el participante reciba información del coordinador
    , hará que el participante permanezca bloqueado.
  2. En el punto único 2PC, todas las solicitudes provienen del coordinador, por lo que el estado del coordinador es crucial. Si el coordinador deja de funcionar, los
    participantes serán bloqueados y ocuparán recursos de transacción.
    Si el coordinador también se distribuye y utiliza el método de selección maestra para proporcionar servicios, luego de que un coordinador cuelga, se puede seleccionar otro coordinador para continuar con los servicios posteriores
    , lo que puede resolver el problema del punto único. Sin embargo, el nuevo coordinador no puede conocer toda la información de estado de la transacción anterior (como el tiempo que ha esperado la respuesta de preparación, etc.
    ), por lo que no puede manejar la transacción anterior sin problemas.
  3. Datos inconsistentes. Durante la transacción de confirmación, la solicitud de confirmación/reversión puede perderse debido al tiempo de inactividad del coordinador o problemas
    de red . Esto da como resultado que algunos participantes no reciban la solicitud de confirmación/reversión, mientras que otros participantes la reciben normalmente. Hasta que se realice la operación de confirmación/reversión
    , los participantes que no hayan recibido la solicitud continuarán bloqueándose. En este punto, los datos ya no son consistentes entre los participantes.
    Cuando el participante ejecuta Commit/Rollback, enviará un Ack al coordinador. Sin embargo, independientemente de si el coordinador recibe el Ack de todos los participantes,
    no habrá otros remedios para la transacción. Todo lo que el coordinador puede hacer es esperar a que tiempo de espera. Luego, el iniciador de la transacción devuelve "No estoy seguro de si la transacción se realizó correctamente
    ".
  4. La confiabilidad del entorno depende del coordinador. Después de emitir la solicitud de preparación, espera una respuesta. Sin embargo, si un participante cae o la red con el coordinador se
    interrumpe, el coordinador no podrá recibir respuestas de todos. participantes. Luego, en 2PC, coordinación El coordinador esperará un cierto período de tiempo y luego, después del tiempo de espera,
    se activará una interrupción de la transacción. Durante este proceso, el coordinador y todos los demás participantes quedan bloqueados.
    Este mecanismo es demasiado severo para entornos del mundo real donde los problemas de red son comunes .

Implementación de transacciones distribuidas en modo AT (transcación automática)

El modo AT es una solución de transacciones distribuidas no intrusiva.
El marco Alibaba Seata implementa este patrón.
En el modo AT, los usuarios solo necesitan prestar atención a su propio "SQL comercial". Como primera etapa del "SQL comercial" del usuario, el marco Seata generará automáticamente las operaciones de confirmación y reversión de dos etapas de la transacción.
Insertar descripción de la imagen aquí
Cómo el modo AT no logra intrusión en el negocio:
Fase uno:
en la primera fase, Seata interceptará el "Business SQL", primero analizará la semántica de SQL y encontrará los
datos . Después de actualizar los datos comerciales, guárdelos como "imagen anterior", luego ejecute "Business SQL" para actualizar los datos comerciales.
Después de actualizar los datos comerciales, guárdelos como "imagen posterior" y finalmente genere un bloqueo de fila. Todas las operaciones anteriores
se completan dentro de una transacción de base de datos, lo que garantiza la atomicidad de las operaciones de una sola etapa.
Si se envía la segunda etapa, debido a que el "SQL comercial" se envió a la base de datos en la primera etapa, el marco Seata solo necesita eliminar
los datos de la instantánea y los bloqueos de fila guardados en la primera etapa para completar la limpieza de datos.
Insertar descripción de la imagen aquí
Insertar descripción de la imagen aquí
Insertar descripción de la imagen aquí
Si la segunda etapa es una reversión, Seata necesita revertir el "SQL comercial" que se ejecutó en la primera etapa y restaurar los datos comerciales. El método de reversión consiste en utilizar la "imagen anterior" para restaurar los datos comerciales, pero antes de restaurar, primero se deben verificar las escrituras sucias. Compare los "datos comerciales actuales de la base de datos" y la "imagen posterior". Si los dos datos son completamente consistentes, significa que hay No hay escrituras sucias. Los datos comerciales se pueden restaurar. Si son inconsistentes, significa que hay escritura sucia. Si ocurre escritura sucia, se requiere procesamiento manual. La
primera y segunda etapa de confirmación y reversión del modo AT se realizan automáticamente. generado por el marco Seata. Los usuarios solo necesitan escribir "SQL comercial". Puede
acceder fácilmente a las transacciones distribuidas. El modo AT es una solución de transacciones distribuidas sin ninguna intrusión en el negocio.

modo TCC

  1. Es relativamente intrusivo y debe implementar la lógica de control de transacciones relevante usted mismo.
    2. Básicamente, no hay bloqueos en todo el proceso y el rendimiento es más fuerte.
    El modo TCC requiere que los usuarios implementen las tres operaciones de probar, confirmar y Cancelar de acuerdo con sus propios escenarios comerciales; el iniciador de la transacción está en la primera etapa
    En el modo de prueba de ejecución del segmento, el método Confirmar se ejecuta durante el envío de la segunda fase y el método Cancelar se ejecuta durante la reversión de la segunda fase.
    Insertar descripción de la imagen aquí

Descripción de los tres métodos de TCC:
Prueba: detección y reserva de recursos;
Confirmar: envío de la operación comercial ejecutada; si la prueba tiene éxito, Confirmar debe tener éxito;
Cancelar: liberación de recursos reservados;
Experiencia práctica de TCC Práctica de
Ant Financial TCC, resumen Las siguientes consideraciones:
➢El modelo de negocio está diseñado en 2 etapas
➢Control de concurrencia
➢Permitir reversión vacía
➢Control anti-colgado
➢Control impotente
1 Diseño de TCC – El modelo de negocio está diseñado en 2 etapas:
los usuarios acceden a TCC, lo más importante es para considerar cómo Nuestro modelo de negocio se divide en dos etapas para implementar.
Tomemos como ejemplo el escenario de "deducir dinero". Antes de conectarse a TCC, la deducción de dinero de la cuenta A se puede
completar . Sin embargo, después de conectarse a TCC, el usuario debe considerar cómo Para cambiar el proceso original de un solo paso, la operación de débito que se puede completar se divide en dos etapas y se implementa
en tres métodos, y se garantiza que si la primera etapa Prueba tiene éxito, la segunda etapa Confirmar será exitosa.
Insertar descripción de la imagen aquí

Como se muestra en la figura anterior, el método Try es un método de preparación de una etapa y requiere verificación y reserva de recursos. En el escenario de deducción de dinero,
lo que Try tiene que hacer es verificar si el saldo de la cuenta es suficiente y reservar los fondos de transferencia. La forma de reservar es congelar los fondos de transferencia en la Cuenta A.
Después de ejecutar el método Try , aunque el saldo de la cuenta A sigue siendo 100, 30 yuanes se han congelado y no se pueden utilizar para otras transacciones.
El método Confirmar de segunda etapa realiza la operación de deducción real. Confirm utilizará los fondos congelados en la etapa de prueba para realizar deducciones de la cuenta.
Después de ejecutar el método Confirmar, los 30 yuanes congelados en la primera etapa de la cuenta A se deducen y el saldo de la cuenta A pasa a ser 70 yuanes.
Si la segunda etapa es una reversión, debe liberar los 30 yuanes congelados en la primera etapa. Pruebe el método Cancelar para que la cuenta A vuelva al
estado inicial y los 100 yuanes estén disponibles.
Cuando los usuarios acceden al modelo TCC, lo más importante es considerar cómo dividir el modelo de negocio en dos fases, implementar los tres métodos TCC
y asegurarse de que Try and Confirm tenga éxito. En comparación con el modo AT, el modo TCC es algo intrusivo para el código comercial
, pero el modo TCC no tiene el bloqueo de fila global del modo AT y el rendimiento de TCC será mucho mayor que el del modo AT.

2.Diseño TCC que permite la reversión vacía.
Insertar descripción de la imagen aquí
El diseño de la interfaz Cancelar debe permitir la reversión vacía. Si no se recibe la interfaz Try debido a la pérdida de paquetes, el administrador de transacciones activará una reversión y
se activará la interfaz Cancel. En este momento, cuando se ejecuta Cancel y se descubre que no hay un xid de transacción o clave primaria correspondiente, necesita devolver una reversión
exitosa. Deje que el administrador del servicio de transacciones piense que se ha revertido; de lo contrario, seguirá intentándolo y Cancelar no tiene datos comerciales correspondientes para revertir
.
3. Diseño TCC: control anti-colgado
Insertar descripción de la imagen aquí
Colgar significa: Cancelar se ejecuta antes de la interfaz Try. La razón es que el tiempo de prueba se agota debido a la congestión de la red, el administrador de transacciones
genera una reversión, activa la interfaz Cancelar y finalmente recibe la interfaz Try. Se llama, pero Cancel llega antes que Try. De acuerdo con la
lógica anterior de permitir la reversión vacía, la reversión regresará con éxito. El administrador de transacciones cree que la transacción se ha revertido con éxito, por lo que la interfaz Try no debe
ejecutarse ; de lo contrario, se producirán inconsistencias en los datos, por lo que cancelamos la reversión vacía Antes de regresar con éxito, registre el xid de la transacción o
la clave principal del negocio para indicar que este registro se ha revertido. La interfaz Try primero verifica el xid de la transacción o la clave principal del negocio. Si se ha marcado como revertido exitosamente,
el No se ejecutará la operación comercial.
4. Diseño TCC: control idempotente
Insertar descripción de la imagen aquí
Idempotencia significa: para el mismo sistema, utilizando las mismas condiciones, una solicitud y múltiples solicitudes repetidas tienen el
mismo impacto en los recursos del sistema. Debido a que la fluctuación o la congestión de la red puede agotarse, el administrador de transacciones volverá a intentar la operación de recursos, por lo que es probable que
se llame repetidamente a una operación comercial. Para no ocupar recursos varias veces debido a llamadas repetidas, el diseño del servicio debe ser idempotente Control, generalmente
podemos usar el xid de transacción o el juicio de clave primaria comercial para controlar.

modo saga

La implementación del modo saga es una solución de transacción larga.
Saga es un protocolo de compensación. En el modo Saga, hay varios participantes en una transacción distribuida. Cada participante es un
servicio de compensación de reversión, que requiere que los usuarios implementen operaciones de avance y operaciones de reversión de reversión de acuerdo con los escenarios comerciales.
Insertar descripción de la imagen aquí

Como se muestra en la figura: T1 T3 son todos procesos de negocios directos y todos corresponden a una operación directa e inversa C1 C3
. Durante la ejecución de una transacción distribuida, las operaciones directas de cada participante se ejecutan en secuencia. Si todas las operaciones directas se ejecutan con éxito, luego
se confirma la transacción de distribución. Si alguna operación de reenvío falla, la transacción distribuida regresará para realizar la
operación de reversión inversa de los participantes anteriores, revertirá a los participantes enviados y devolverá la transacción distribuida al estado inicial.
Los desarrolladores de negocios también deben implementar los servicios de Saga Forward y los servicios de compensación. Por tanto, se trata de una intrusión empresarial.
Las transacciones distribuidas en el modo Saga generalmente se basan en eventos y cada participante se ejecuta de forma asincrónica. El modo Saga es una
solución de transacción larga.

Escenarios de uso del modo Saga El
modo Saga es adecuado para sistemas comerciales con procesos comerciales largos y la necesidad de garantizar la coherencia final de las transacciones. El modo Saga enviará
transacciones locales en una etapa y puede garantizar el rendimiento en el caso de procesos largos y sin bloqueos. .
Los participantes de la transacción pueden ser servicios de otras empresas o servicios de sistemas heredados que no se pueden transformar y proporcionar las interfaces requeridas por TCC, por lo que se
puede utilizar el modo Saga.
Las ventajas del modelo Saga son:
envío en una sola etapa de transacciones de bases de datos locales, sin bloqueos, alto rendimiento;
los participantes pueden utilizar la ejecución asincrónica impulsada por transacciones, alto rendimiento;
el servicio de compensación es el "inverso" del servicio directo, fácil comprender e implementar
Desventajas: el modo Saga no puede garantizar
el aislamiento . Las respuestas a la falta de aislamiento se discutirán más adelante.
Lo mismo que la experiencia práctica de TCC es que en el modo Saga, las operaciones inversas e inversas de cada participante de la transacción deben admitir:
compensación vacía: la operación inversa es anterior a la operación directa;
control anti-colgado: la operación directa debe ser rechazado después de una compensación vacía Operación
idempotente

modo XA

Modo XA
XA es un protocolo de confirmación de dos fases definido por el grupo X/Open DTP
.
El modelo X/Open DTP (1994) incluye programa de aplicación (AP), administrador de transacciones (TM) y administrador de recursos (RM).
Las funciones de la interfaz XA las proporcionan los proveedores de bases de datos. La base de la especificación XA es el protocolo de confirmación de dos fases 2PC.
JTA (Java Transaction API) es una interfaz mejorada de la especificación XA implementada en Java.
En el modo XA, se requiere un coordinador [global]. Después de completar cada transacción de la base de datos, se realiza la primera fase de confirmación previa, se notifica al coordinador
y se le entregan los resultados. Después de que el coordinador complete todas las operaciones de transacción de sucursal y las confirme previamente, continúe con el segundo paso; el segundo paso: el coordinador
notifica a cada base de datos que se comprometa/revierta una por una.
Entre ellos, el coordinador global es el rol de TM en el modelo XA, y la base de datos de cada transacción de sucursal es el RM.
Implementación XA proporcionada por MySQL (https://dev.mysql.com/doc/refman/5.7/en/xa.html)
El marco de código abierto en modo XA es atomikos, y su empresa de desarrollo también tiene una versión comercial.
Desventajas del modo XA: gran granularidad de transacciones. En condiciones de alta concurrencia, la disponibilidad del sistema es baja. Por eso rara vez se utiliza.

( AT TCC, Saga,
, costo de aprendizaje es casi nulo. El modo TCC es una solución de transacciones distribuidas de alto rendimiento, adecuada para escenarios con requisitos de alto rendimiento, como los sistemas centrales. El modo Saga es una solución de transacciones largas, adecuada para sistemas comerciales con procesos comerciales largos y la necesidad de garantizar la coherencia final de las transacciones. El modo Saga enviará transacciones locales en una etapa, sin bloqueos, y puede garantizar el rendimiento en situaciones de procesos largos. se utiliza principalmente en la capa de canal, sistema empresarial de capa integrada. Los participantes de la transacción pueden ser servicios de otras empresas o servicios de sistemas heredados que no se pueden transformar y proporcionar las interfaces requeridas por TCC. También se puede utilizar el modo Saga. El modo XA es una solución para una fuerte coherencia distribuida, pero su rendimiento es bajo y rara vez se utiliza.







Uso de transacciones distribuidas de Seata

Seata es una solución de transacciones distribuidas de código abierto dedicada a proporcionar servicios de transacciones distribuidas de alto rendimiento y fáciles de usar. Seata proporcionará a los usuarios modos de transacción AT, TCC, SAGA y XA para crear una solución distribuida integral para los usuarios. El modo AT es el primer modo recomendado por Alibaba. Existe una versión comercial de GTS (Global Transaction Service) en Alibaba Cloud.

Las tres funciones principales de Seata
En la arquitectura de Seata, hay tres funciones: TC (Coordinador de transacciones): el coordinador de transacciones mantiene el estado de las transacciones globales y de sucursales e impulsa el envío o la reversión de transacciones globales. TM (Administrador de transacciones): el administrador de transacciones define el alcance de una transacción global: inicia una transacción global, confirma o revierte una transacción global.
RM (Administrador de recursos): el administrador de recursos administra los recursos para el procesamiento de transacciones de sucursales, habla con el TC para registrar las transacciones de sucursales e informar el estado de las transacciones de sucursales, y hace que las transacciones de sucursales se confirmen o reviertan. Entre ellos, TC es un servidor implementado por separado, y TM y RM son clientes integrados en la aplicación.

Ciclo de vida de transacciones distribuidas

En Seata, el ciclo de vida de una transacción distribuida es el siguiente:
Insertar descripción de la imagen aquí
1. TM solicita a TC que inicie una transacción global. TC generará un XID como número de la transacción global. XID se propagará en el enlace de llamada de los microservicios para garantizar que
las subtransacciones de múltiples microservicios estén asociadas entre sí.
Al ingresar al método de transacción, se generará un XID y global_table es la información de la transacción global almacenada.
2.RM solicita a TC que registre la transacción local como una transacción de sucursal de la transacción global y la asocie a través del XID de la transacción global. .
Al ejecutar el método de operación de la base de datos, el participante
3.TM de la transacción de almacenamiento Branch_table solicita a TC que le indique al XID si la transacción global correspondiente se confirma o se revierte.
4. TC impulsa a los RM a confirmar o revertir sus propias transacciones locales correspondientes al XID.

El núcleo del modo AT es la no intrusión en el negocio. Es un envío mejorado de dos etapas. Su idea de diseño es como se muestra en la figura. En la
primera etapa,
los datos comerciales y los registros de reversión se envían en el mismo local. transacción y se liberan bloqueos locales y recursos de conexión. El núcleo es analizar el SQL empresarial, convertirlo en deshacer registro y
almacenarlo en la base de datos al mismo tiempo ¿Cómo se hace esto? Primero, descartemos el concepto de fuente de datos proxy DataSourceProxy. Probablemente pueda adivinar cuál es la operación por el nombre. Haremos un análisis detallado más adelante. En la
segunda etapa
, si la operación de transacción distribuida tiene éxito, TC notificará RM para eliminar de forma asincrónica el deshacer registro.
La operación de transacción distribuida falló. TM envía una solicitud de reversión a TC, y RM recibe la solicitud de reversión del TC coordinador, encuentra el registro de reversión correspondiente a través de XID y ID de sucursal, y genera el SQL de actualización inversa. a través del registro de reversión y lo ejecuta para completar la rama de reversión.

En comparación con otros marcos de transacciones distribuidas, los aspectos más destacados de la arquitectura Seata incluyen:

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

Pérdida de rendimiento
Una actualización de SQL requiere la adquisición de xid de transacción global (comunicación con TC), antes de la imagen (analizando el SQL, consultando la base de datos una vez), después de la imagen (consultando la base de datos una vez), insertando el registro de deshacer (escribiendo en la base de datos una vez), antes commit (comunicarse con TC, determinar conflictos de bloqueo), estas operaciones requieren un RPC de comunicación remota y son sincrónicas. Además, el rendimiento de inserción de campos de blob al escribir el registro de deshacer tampoco es alto. Cada declaración SQL agregará mucha sobrecarga y se estima aproximadamente que el tiempo de respuesta aumentará 5 veces. Rentabilidad
Para realizar una compensación automática, es necesario generar y conservar espejos frontales y traseros para todas las transacciones, pero en escenarios comerciales reales, ¿qué tan alta es la tasa de éxito o qué proporción de transacciones distribuidas deben revertirse? si fallan? Según la regla 80/20, para revertir el 20% de las transacciones, el tiempo de respuesta del 80% de las transacciones exitosas debe multiplicarse por 5. ¿Vale la pena este costo en comparación con pedirle a la aplicación que desarrolle una transacción de compensación? ?
Datos del punto de acceso de bloqueo global En comparación con XA, Seata liberará el bloqueo de la base de datos después de que la primera etapa sea exitosa, pero la determinación del bloqueo global antes de la confirmación en la primera etapa también alarga el tiempo de retención del bloqueo de datos. Los XA se preparan y realizan pruebas basadas en escenarios comerciales reales. La introducción de bloqueos globales logra el aislamiento, pero el problema que trae es el bloqueo y la reducción de la concurrencia, especialmente para datos calientes, este problema será más grave. Tiempo de liberación del bloqueo de reversión
Cuando Seata retrocede, necesita eliminar el registro de deshacer de cada nodo antes de liberar el bloqueo en la memoria TC. Por lo tanto, si la segunda etapa es una reversión, el tiempo para liberar el bloqueo será más largo.
Problema de interbloqueo La
introducción de bloqueos globales por parte de Seata aumentará el riesgo de interbloqueos. Sin embargo, si se produce un interbloqueo, continuará reintentando y finalmente esperará a que expire el tiempo de bloqueo global. Este método no es elegante y también prolonga la ocupación del bloqueo de la base de datos.tiempo.

Uso rápido de Seata.

https://seata.io/zh-cn/docs/ops/deploy-guide-beginner.htmlDescargue
el paquete de instalación

El modo de almacenamiento del lado del servidor (store.mode) admite tres tipos:
archivo: (predeterminado) modo independiente, la información de la sesión de transacción global se lee y escribe en la memoria y el archivo local root.data se conserva, con alto rendimiento (predeterminado)
db: (5.7+) En modo de alta disponibilidad, la información de la sesión de transacción global se comparte a través de db y el rendimiento correspondiente es deficiente.
Abra config/file.conf
y modifique mode="db"
para modificar la información de conexión de la base de datos (URL \ NOMBRE DE USUARIO\CONTRASEÑA) .
Cree la base de datos seata_server y cree
una nueva tabla: puede ir a la proporcionada por seata. Descargar desde Información de recursos:
haga clic para ver
\script\server\db\mysql.sql
la tabla de sucursales almacena la información de los participantes de las transacciones.

1
2 store {
    
    
3  mode = "db"
4
5  db {
    
    
6  ## the implement of javax.sql.DataSource, such as DruidDataSource(druid)/BasicDataSource(dbcp)/HikariDataSource(hik
ari) etc.
7  datasource = "druid"
8  ## mysql/oracle/postgresql/h2/oceanbase etc.
9  dbType = "mysql"
10  driverClassName = "com.mysql.jdbc.Driver"
11  url = "jdbc:mysql://192.168.65.220:3306/seata_server"
12  user = "root"
13  password = "123456"
14  minConn = 5
15  maxConn = 30
16  globalTable = "global_table"
17  branchTable = "branch_table"
18  lockTable = "lock_table"
19  queryLimit = 100
20  maxWait = 5000
21 }
22 }

redis: compatible con Seata-Server 1.3 y superior, con alto rendimiento, pero existe el riesgo de perder información de la transacción. Configure de antemano el
directorio de recursos de configuración de persistencia de redis adecuado para el escenario actual: https://github.com/seata /seata/tree/1.3 .0/script
client
almacena scripts sql del lado del cliente, configuración de parámetros
config-center
y cada script de importación de parámetros del centro de configuración.config.txt (incluido el servidor y el cliente, anteriormente conocido como nacos-config.txt) es un script de base de datos del lado del
servidor del servidor de archivos de parámetros generales y la configuración de cada contenedor

Paso 5: Configure el centro de registro de Nacos para que sea responsable de los participantes de la transacción (microservicios) y la comunicación TC.
Registre el servidor Seata en Nacos, modifique la configuración de registro.conf en el directorio conf
y luego inicie el centro de registro del servidor Nacos
1 #Ingrese Directorio de instalación de Nacos e inicio de Linux independiente
2 bin/startup.sh ‐m standalone
3 # inicio independiente de Windows
4 bin/startup.bat
Paso 6: Configurar el Centro de configuración de Nacos
Turing Classroom

Nota: Si el servidor seata está configurado para usar nacos como centro de configuración, la información de configuración se leerá desde nacos y no es necesario configurar file.conf. Al configurar el registro.conf en el lado del cliente
y usar nacos, también debe prestar atención a que el grupo sea consistente con el grupo en el servidor seata. El grupo predeterminado es "DEFAULT_GROUP".
Obtenga /seata/script/config-center/config .txt y modifique la información de configuración
para configurar el grupo de transacciones. Consistente con el grupo de transacciones configurado en el cliente
#my_test_tx_group debe ser consistente con el cliente default debe ser consistente con el cliente y el clúster en el registro en registro.conf
( configuración de propiedades del cliente: spring.cloud.alibaba.seata.tx-service-group=my_test_tx_group)
Agrupación de transacciones: My_test_tx_group, un mecanismo de tolerancia a fallas de energía de la sala de computadoras remota,
se puede personalizar, por ejemplo: (guangzhou, shanghai...), y el cliente correspondiente también debe configurar
1 seata.service.vgroup-mapping.projectA=guangzhou
default debe ser igual al registro.confi cluster =
parámetros de configuración “predeterminados” sincronizados con
el shell de Nacos:
1 sh ${SEATAPATH}/script/config‐ center/nacos/nacos‐config.sh ‐h localhost ‐p 8848 ‐g SEATA_GROUP ‐t 5a3c7d6c‐f497‐
4d68‐ a71a-2e5e3340b3ca
Descripción del parámetro:
-h: host, el valor predeterminado es localhost
-p: puerto, el valor predeterminado es 8848
-g: configurar grupo, el valor predeterminado es 'SEATA_GROUP'
Turing Classroom
-t: información del inquilino, correspondiente al campo ID del espacio de nombres de Nacos, el valor predeterminado está vacío''
configuración delgada
1 service.vgroupMapping.my_test_tx_group=default
2 service.default .grouplist=127.0.0.1:8091
3 service.enableDegrade=false
4 service.disableGlobalTransaction=false
5 store.mode=db
6 store.db.datasource=druid
7 store.db.dbType=mysql
8 store.db.driverClassName=com .mysql.jdbc.Driver
9 store.db.url=jdbc:mysql://127.0.0.1:3306/seata?useUnicode= true
10 store.db.user=root
11 store.db.password=root
12 store.db .minConn=5
13 store.db.maxConn=30
14 store.db.globalTable=global_table
15 store.db.branchTable=branch_table
16 store.db.queryLimit=100
17 store.db.lockTable=lock_table
18 store.db.maxWait =5000
Paso 7: Inicie el código fuente del servidor Seata : ejecute el comando del método principal
de io.seata.server.Server.java en el módulo del servidor Iniciar Seata Server 1 bin/seata‐server.sh ‐p 8091 ‐n 1 1 bin/seata‐server.sh ‐p 8092 ‐n 2 1 bin/seata‐server.sh ‐p 8093 ‐n 3 se inició correctamente, el puerto predeterminado es 8091 y puede ver en el centro de registro que el servidor seata se ha registrado correctamente.






Inicio rápido del cliente Seata
La implementación de transacciones declarativas (@GlobalTransactional)
está conectada a la aplicación de microservicio.
Escenario empresarial:
el usuario realiza un pedido. Toda la lógica empresarial consta de tres microservicios:
Servicio de pedido: crea un pedido basado en los requisitos de adquisición.
Servicio de inventario: deduzca la cantidad de inventario de un artículo determinado.
1) Inicie el servidor Seata. El servidor Seata utiliza nacos como centro de configuración y centro de registro (el paso anterior se ha completado)
2) Configure microservicios para integrar seata
. Paso 1: agregue la dependencia pom

1 <!‐‐ seata‐‐>
2 <dependency>
3 <groupId>com.alibaba.cloud</groupId>
4 <artifactId>spring‐cloud‐starter‐alibaba‐seata</artifactId>
5 </dependency>

Paso 2: agregue la tabla undo_log a la base de datos correspondiente de cada microservicio

1 CREATE TABLE `undo_log` (
2 `id` bigint(20) NOT NULL AUTO_INCREMENT,
3 `branch_id` bigint(20) NOT NULL,
4 `xid` varchar(100) NOT NULL,
5 `context` varchar(128) NOT NULL,
6 `rollback_info` longblob NOT NULL,
7 `log_status` int(11) NOT NULL,
8 `log_created` datetime NOT NULL,
9 `log_modified` datetime NOT NULL,
10 PRIMARY KEY (`id`),
11 UNIQUE KEY `ux_undo_log` (`xid`,`branch_id`)
12 ) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8;

Paso 5: Modifique Register.conf y configure nacos como registro.type&config.type. El servidor seata correspondiente también usa nacos.
Nota: Debe especificar group = "SEATA_GROUP" porque el servidor Seata especifica group = "SEATA_GROUP", que debe ser coherente.

1 registry {
    
    
2  # file 、nacos 、eureka、redis、zk、consul、etcd3、sofa
3  type = "nacos"
4
5  nacos {
    
    
6  serverAddr = "localhost"
7  namespace = ""
8  cluster = "default"
9  group = "SEATA_GROUP"
10 }
11 }
12 config {
    
    
13  # file、nacos 、apollo、zk、consul、etcd3、springCloudConfig
14  type = "nacos"
15
16  nacos {
    
    
17  serverAddr = "localhost"
18  namespace = ""
19  group = "SEATA_GROUP"
20 }
21 }
22

Si ocurre este problema:
En la mayoría de los casos, se debe a una falta de coincidencia en la configuración:
1. Verifique si el servicio seata utilizado actualmente es consistente con la versión de seata en el proyecto maven
2. Verifique tx-service-group, nacos.cluster, ¿son los nacos? ¿El parámetro .group es consistente con la configuración en Seata Server?
Código fuente de seguimiento: RegistryService#lookup se implementa en el paquete seata/discover para obtener la lista de servicios
1 NacosRegistryServiceImpl#lookup
2 》String clusterName = getServiceGroup(key); #Obtener el servidor seata Nombre del clúster
3 》List firstAllInstances = getNamingInstance().getAllInstances(getServiceName(), getServiceGroup(), cluster
rs)
Paso 6: Modifique la configuración de application.yml para configurar
la agrupación de transacciones del servicio seata, que debe ser coherente con service.vgroup_mapping en el centro de configuración del servidor nacos Correspondencia de sufijos

1 server:
2  port: 8020
3
4 spring:
5  application:
6  name: order‐service
7  cloud:
8  nacos:
9  discovery:
10  server‐addr: 127.0.0.1:8848
11  alibaba:
12  seata:
13  tx‐service‐group:
14  my_test_tx_group # seata 服务事务分组
15
16  datasource:
17  type: com.alibaba.druid.pool.DruidDataSource
18  druid:
19  driver‐class‐name: com.mysql.cj.jdbc.Driver
20  url: jdbc:mysql://localhost:3306/seata_order?useUnicode=true&characterEncoding=UTF‐8&serverTimezone=Asia/Shanghai
21  username: root
22  password: root
23  initial‐size: 10
24  max‐active: 100
25  min‐idle: 10
26  max‐wait: 60000
27  pool‐prepared‐statements: true
28  max‐pool‐prepared‐statement‐per‐connection‐size: 20
29  time‐between‐eviction‐runs‐millis: 60000
30  min‐evictable‐idle‐time‐millis: 300000
31  test‐while‐idle: true
32  test‐on‐borrow: false
33  test‐on‐return: false
34  stat‐view‐servlet:
35  enabled: true
36  url‐pattern: /druid/*
37  filter:
38  stat:
39  log‐slow‐sql: true
40  slow‐sql‐millis: 1000
41  merge‐sql: false
42  wall:
43  config:
44  multi‐statement‐allow: true

Paso 7: el iniciador del microservicio (parte TM) debe agregar la anotación @GlobalTransactional

1 @Override
2 //@Transactional
3 @GlobalTransactional(name="createOrder")
4 public Order saveOrder(OrderVo orderVo){
    
    
5  log.info("=============用户下单=================");
6  log.info("当前 XID: {}", RootContext.getXID());
7
8 // 保存订单
9  Order order = new Order();
10  order.setUserId(orderVo.getUserId());
11  order.setCommodityCode(orderVo.getCommodityCode());
12  order.setCount(orderVo.getCount());
13  order.setMoney(orderVo.getMoney());
14  order.setStatus(OrderStatus.INIT.getValue());
15
16  Integer saveOrderRecord = orderMapper.insert(order);
17  log.info("保存订单{}", saveOrderRecord > 0 ? "成功" : "失败");
18
19 //扣减库存
20  storageFeignService.deduct(orderVo.getCommodityCode(),orderVo.getCount());
21
22 //扣减余额
23  accountFeignService.debit(orderVo.getUserId(),orderVo.getMoney());
24
25 //更新订单
26  Integer updateOrderRecord = orderMapper.updateOrderStatus(order.getId(),OrderStatus.SUCCESS.getValue());
27  log.info("更新订单id:{} {}", order.getId(), updateOrderRecord > 0 ? "成功" : "失败");
28
29 return order;
30
31 }

Supongo que te gusta

Origin blog.csdn.net/wangjunlei666/article/details/129886449
Recomendado
Clasificación