El viaje de las transacciones distribuidas a partir de la instalación de Seata springboot integrado seata

inserte la descripción de la imagen aquí

introducir

¿Qué es Seata?

En el desarrollo de aplicaciones modernas, los sistemas distribuidos se utilizan cada vez más. Sin embargo, a medida que aumenta la complejidad del sistema, se vuelve cada vez más difícil manejar transacciones distribuidas. Este es el trasfondo en el que surge Seata. Seata (Simple Extensible Autonomous Transaction Architecture) es una solución de transacciones distribuidas de código abierto diseñada para resolver problemas de consistencia y coordinación de transacciones en sistemas distribuidos.
En las aplicaciones monolíticas tradicionales, las bases de datos relacionales suelen utilizarse para gestionar transacciones y garantizar la coherencia de los datos. Pero en un sistema distribuido, la gestión de transacciones se vuelve complicada porque están involucrados múltiples servicios independientes. El requisito de una transacción distribuida es que todos los servicios involucrados se confirmen con éxito o se reviertan para mantener la consistencia de los datos.

Seata proporciona dos modos de transacción principales:

  1. Modo AT (Modo de compensación automática): En el modo AT, Seata compensará automáticamente las transacciones sin escribir manualmente la lógica de compensación. Seata organizará todas las operaciones de la transacción en una transacción global, luego ejecutará la operación de prueba de cada sucursal y realizará la operación de compensación correspondiente cuando ocurra una excepción.

  2. Modo TCC (modo de compromiso de dos fases): el modo TCC requiere que los desarrolladores escriban manualmente la lógica de las tres fases de Probar, Confirmar y Cancelar. En el modo TCC, Seata es responsable de coordinar el compromiso y la reversión de las transacciones globales, mientras que los desarrolladores implementan las operaciones de prueba, confirmación y cancelación de cada sucursal.

Seata también proporciona soporte de almacenamiento y registro escalable, lo que lo hace adecuado para varios escenarios.

En general, Seata es una poderosa solución de transacciones distribuidas que puede ayudar a los desarrolladores a resolver problemas de transacciones distribuidas y garantizar la consistencia y confiabilidad de los datos en sistemas distribuidos. Al integrar Seata, los desarrolladores pueden construir más fácilmente aplicaciones distribuidas complejas y mejorar la estabilidad y el rendimiento del sistema.

Instalar servidor de Seat

Descarga la versión de Seata Server

Puede descargar la última versión de Seata Server desde el sitio web oficial de Seata y descomprimirlo en un directorio específico; hay versiones fuente y binaria, aquí elegimos instalar el archivo binario para descargar. Mi versión es 1.7.0 (2023-07-11, versión recomendada)
inserte la descripción de la imagen aquí

Configurar Seata

descomprimir archivos

inserte la descripción de la imagen aquí
El archivo descargado es un archivo zip, y después de la descompresión, será la carpeta de arriba. El nombre de carpeta predeterminado es seata.

Configurar el archivo yml de Seata

Ingrese seata/confal directorio, hay dos archivos de configuración aquí, necesitamos application.ymlmodificar un nombre a voluntad y luego application.example.ymlmodificarlo application.ymlcomo el archivo de configuración principal.
inserte la descripción de la imagen aquí
Modifique application.ymlel archivo, aquí uso nacos como centro de registro, por lo que los lugares que deben modificarse son:

  1. asiento:config:tipo
  2. seata:registro:tipo
  3. tienda: modo
  4. tienda:sesión:modo
  5. tienda: bloqueo: modo
  6. store:db La configuración de la base de datos se modifica a su propia

Archivo de configuración:

server:
  port: 7091

spring:
  application:
    name: seata-server

logging:
  config: classpath:logback-spring.xml
  file:
    path: ${
    
    user.home}/logs/seata
  extend:
    logstash-appender:
      destination: 127.0.0.1:4560
    kafka-appender:
      bootstrap-servers: 127.0.0.1:9092
      topic: logback_to_logstash
# 这里是主要的配置文件
seata:
  config:
    # support: nacos 、 consul 、 apollo 、 zk  、 etcd3
    type: nacos
    nacos:
      server-addr: 127.0.0.1:8848
      # 如果在nacos上添加了命名空间,则配置命令空间ID
      namespace:
      # 配置分组
      group: SEATA_GROUP
      username:
      password:
      context-path:
      ##if use MSE Nacos with auth, mutex with username/password attribute
      #access-key:
      #secret-key:
      data-id: seataServer.properties
  registry:
    # support: nacos 、 eureka 、 redis 、 zk  、 consul 、 etcd3 、 sofa
    type: nacos
    preferred-networks: 30.240.*
    nacos:
      application: seata-server
      server-addr: 127.0.0.1:8848
      group: SEATA_GROUP
      namespace:
      cluster: default
      username:
      password:
      context-path:
      ##if use MSE Nacos with auth, mutex with username/password attribute
      #access-key:
      #secret-key:
  server:
    service-port: 8091 #If not configured, the default is '${server.port} + 1000'
    max-commit-retry-timeout: -1
    max-rollback-retry-timeout: -1
    rollback-retry-timeout-unlock-enable: false
    enable-check-auth: true
    enable-parallel-request-handle: true
    retry-dead-threshold: 130000
    xaer-nota-retry-timeout: 60000
    enableParallelRequestHandle: true
    recovery:
      committing-retry-period: 1000
      async-committing-retry-period: 1000
      rollbacking-retry-period: 1000
      timeout-retry-period: 1000
    undo:
      log-save-days: 7
      log-delete-period: 86400000
    session:
      branch-async-queue-size: 5000 #branch async remove queue size
      enable-branch-async-remove: false #enable to asynchronous remove branchSession
  store:
    # support: file 、 db 、 redis
    mode: db
    session:
      mode: db
    lock:
      mode: db
    db:
      datasource: druid
      db-type: mysql
      driver-class-name: com.mysql.jdbc.Driver
      url: jdbc:mysql://127.0.0.1:3306/seata?rewriteBatchedStatements=true
      user: mysql
      password: mysql
      min-conn: 10
      max-conn: 100
      global-table: global_table
      branch-table: branch_table
      lock-table: lock_table
      distributed-lock-table: distributed_lock
      query-limit: 1000
      max-wait: 5000
  metrics:
    enabled: false
    registry-type: compact
    exporter-list: prometheus
    exporter-prometheus-port: 9898
  transport:
    rpc-tc-request-timeout: 15000
    enable-tc-server-batch-send-response: false
    shutdown:
      wait: 3
    thread-factory:
      boss-thread-prefix: NettyBoss
      worker-thread-prefix: NettyServerNIOWorker
      boss-thread-size: 1

Cargue el archivo de configuración config.txt a nacos

Modificar el archivo config.txt

config.txtEl archivo está en seata/script/config-centerel directorio, los lugares que necesitamos modificar son:

  1. tienda.modo=db
  2. store.lock.mode=db
  3. store.session.mode=db
  4. La configuración de la base de datos store.db se modifica por sí misma, que es la misma que en el archivo yml anterior

Cargalo en nacos

Introduzca seata/script/config-center/nacosel directorio para ejecutar nacos-config.shel archivo.

sh nacos-config.sh -h 121.37.228.169 -p 8848 -g SEATA_GROUP -t 0af6e97b-a684-4647-b696-7c6d42aecce7 -u nacos -w nacos
  • -h: dirección IP de Nacos
  • -p: número de puerto Nacos
  • -g: nombre del grupo del grupo
  • -t: ID de espacio de nombres, si no es público de forma predeterminada
  • -u: nombre de usuario
  • -w: contraseña
    Una vez completada la ejecución, inicie sesión en nuestra gestión de configuración de Nacos para ver los datos cargados:
    inserte la descripción de la imagen aquí

Iniciar el servicio Seata

Comienzo normal

Ingrese seata/binal directorio y ejecute el comando:

sh seata-server.sh 

inserte la descripción de la imagen aquí

Aquí puedo encontrar una situación anormal cuando lo inicio. A continuación, he enumerado algunas dificultades que encontré al iniciarlo. puede moverse a启动时遇到的坑

Ver registro de inicio

Mi sistema Mac está abierto para abrir archivos de registro. Otros sistemas necesitan ejecutar comandos de acuerdo con el sistema, o ingresar directamente al seata/logsdirectorio para ver start.outlos archivos.

open /Users/ddz/Downloads/seata/logs/start.out

inserte la descripción de la imagen aquí
Puede ver la dirección de salida del registro que indica que el inicio se realizó correctamente.

Abre la página de la consola

En la página de la consola , la contraseña de cuenta predeterminada es seata/seata.
inserte la descripción de la imagen aquí

Hoyo encontrado al inicio

Aquí hay algunas dificultades que encontré al implementar Seata, y puede haber diferencias entre ellas solo como referencia.

No se puede resolver el valor de ${console.user.username}

Información de excepción : no se pudo resolver el marcador de posición 'console.user.username' en el valor "${console.user.username}"
inserte la descripción de la imagen aquí
Solución : debe copiar toda la información de configuración en el archivo yml que se modificó previamente con otro nombre consoleal actual application.ymluno Aquí se establece la contraseña de la cuenta para nuestra página de consola de inicio de sesión.

No se puede analizar el valor de ${seata.security.secretKey}

Información de excepción : no se pudo resolver el marcador de posición 'seata.security.secretKey' en el valor "${seata.security.secretKey}"
inserte la descripción de la imagen aquí
Solución : debe copiar toda la información de configuración en el archivo yml que se modificó previamente con otro nombre seata.securityal actual application.ymluno

problema de conexion a la base de datos

Información de excepción : com.mysql.jdbc.exceptions.jdbc4.CommunicationsException: falla del enlace de comunicaciones
En versiones anteriores a MySQL5.7, la seguridad es baja y cualquier usuario puede conectarse a la base de datos, por lo que la versión oficial 5.7 ha aumentado la protección de la privacidad. Y se adopta el valor predeterminado useSSL = true para evitar la modificación aleatoria de la base de datos.En la versión 8.0, aún se conserva SSL y el valor predeterminado es true.
inserte la descripción de la imagen aquí

Solución : agregue después de la URL de configuración de la base de datos &useSSL=false; debe verificar el archivo de configuración yml y la lista de configuración en Nacos store.db.url.
inserte la descripción de la imagen aquí

Integrar Seata en el proyecto Spring Boot

Anteriormente presentamos cómo instalar el servidor seata localmente y luego presentamos la integración de seata en nuestro proyecto Spring Boot; aquí solo uso una demostración para presentarlo, que puede implementarse de acuerdo con su propia lógica comercial.

ambiente de trabajo

  • MySQL 5.7.28
  • Experto 3.5.4
  • JDK 1.8
  • Mibot 3.4.1
  • dinámico 3.4.1

nube, arranque, entorno alibaba

   <spring-boot.version>2.3.7.RELEASE</spring-boot.version>
   <spring-cloud.version>Hoxton.SR9</spring-cloud.version>
   <spring-cloud-alibaba.version>2.2.6.RELEASE</spring-cloud-alibaba.version>

agregar dependencias

	<!--    MySQL    -->
	<dependency>
	    <groupId>mysql</groupId>
	    <artifactId>mysql-connector-java</artifactId>
	</dependency>
	<!--    Mybatis    -->
	<dependency>
	    <groupId>com.baomidou</groupId>
	    <artifactId>mybatis-plus-boot-starter</artifactId>
	    <version>3.4.1</version>
	</dependency>
	<!--    多数据源    -->
	<dependency>
	    <groupId>com.baomidou</groupId>
	    <artifactId>dynamic-datasource-spring-boot-starter</artifactId>
	    <version>3.4.1</version>
	</dependency>
	<!--    Seata分布式事务    -->
	<dependency>
	    <groupId>com.alibaba.cloud</groupId>
	    <artifactId>spring-cloud-starter-alibaba-seata</artifactId>
	</dependency>

configuración yml

server:
  port: 7001
spring:
  application:
    name: ddz-user
  cloud:
    nacos:
      discovery:
        # 服务分组
        group: ddz
        server-addr: 121.37.228.111:8848
        # 必须填命名空间的ID
#        namespace: 9ebef975-dcc0-4430-9c63-1c62d8a86d82
  datasource:
    dynamic:
      # 开启seata分布式事务
      seata: true
      strict: false
      primary: master
      datasource:
        master:
          url: jdbc:mysql://121.37.228.111:3306/ddz?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8&rewriteBatchedStatements=true
          username: ddz
          password: ddz2023
        local:
          url: jdbc:mysql://127.0.0.1:3306/ddz?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8&rewriteBatchedStatements=true
          username: root
          password: ddz2023

# MyBatis Plus配置
mybatis-plus:
  # 搜索指定包别名
  typeAliasesPackage: com.ddz.**.entity
  # 配置mapper的扫描,找到所有的mapper.xml映射文件
  mapperLocations: classpath*:mapper/**/*.xml
  global-config:
    db-config:
      id-type: auto
  configuration:
    # 开启驼峰,开启后,只要数据库字段和对象属性名字母相同,无论中间加多少下划线都可以识别
    map-underscore-to-camel-case: true

# Seata 配置
seata:
  application-id: seata-server
  # 是否启用数据源bean的自动代理
  enable-auto-data-source-proxy: false
  tx-service-group: default_tx_group  # 必须和服务器配置一样
  registry:
    type: nacos
    nacos:
      # Nacos 服务地址
      server-addr: 121.37.228.111:8848
      group: SEATA_GROUP
#      namespace: 9ebef975-dcc0-4430-9c63-1c62d8a86d82
      application: seata-server # 必须和服务器配置一样
      #      username:
      #      password:
      cluster: default
  config:
    type: nacos
    nacos:
      server-addr: 121.37.228.111:8848
      group: SEATA_GROUP
#      namespace: 9ebef975-dcc0-4430-9c63-1c62d8a86d82
  service:
    vgroup-mapping:
      default_tx_group: default # 必须和服务器配置一样
    disable-global-transaction: false
  client:
    rm:
      # 是否上报成功状态
      report-success-enable: true
      # 重试次数
      report-retry-count: 5

Integrar Seata en el código empresarial

Creamos dos mapperclases basadas en dos fuentes de datos y luego controllerlas probamos; omito la capa empresarial por la conveniencia de probar aquí.

Use @GlobalTransactionalanotaciones para administrar transacciones globales

inserte la descripción de la imagen aquí

Demuestra el modo AT (compensación automática) y el modo TCC (compromiso de dos fases)

Utilice el modo AT (compensación automática)

En el modo AT, Seata compensará automáticamente las transacciones sin escribir manualmente la lógica de compensación. Primero, demostremos un escenario de transferencia simple, transfiriendo fondos de una cuenta a otra y asegurando la consistencia de la transacción.

  1. Agregue la anotación @GlobalTransactional
    Agregue la anotación @GlobalTransactional al método del servicio de transferencia para marcar la transacción global:
@Service
public class TransferService {
    
    
    
    @GlobalTransactional
    public void transfer(String fromAccount, String toAccount, double amount) {
    
    
        // 扣除转出账户金额
        deductAmount(fromAccount, amount);

        // 增加转入账户金额
        addAmount(toAccount, amount);
    }

    // 实现扣除金额逻辑
    // ...

    // 实现增加金额逻辑
    // ...
}
  1. Pruebe el modo AT
    Escriba casos de prueba para verificar la gestión de transacciones en modo AT:
@RunWith(SpringRunner.class)
@SpringBootTest
public class TransferServiceTest {
    
    

    @Autowired
    private TransferService transferService;

    @Test
    public void testTransfer() {
    
    
        // 假设从账户 A 转账 100 到账户 B
        transferService.transfer("accountA", "accountB", 100.0);
    }
}

Ejecute el caso de prueba para observar si la transferencia es exitosa y verifique el registro para confirmar si Seata compensó automáticamente la transacción.

Usar el modo TCC (compromiso de dos fases)

En el modo TCC, necesitamos escribir manualmente la lógica de las tres fases de Probar, Confirmar y Cancelar para asegurar la correcta ejecución de la transacción. Demostremos un escenario simple de creación de pedidos, que incluye tres etapas: realizar un pedido, deducir el inventario y crear un pedido.

  1. Implemente la interfaz TCC
    Cree una interfaz TCC e implemente la lógica de las tres etapas de Probar, Confirmar y Cancelar:
public interface OrderTccService {
    
    

    @GlobalTransactional
    boolean createOrder(OrderDTO orderDTO);

    @TwoPhaseBusinessAction(name = "orderTccService", commitMethod = "confirmOrder", rollbackMethod = "cancelOrder")
    boolean tryCreateOrder(OrderDTO orderDTO);

    boolean confirmOrder(OrderDTO orderDTO);

    boolean cancelOrder(OrderDTO orderDTO);
}
  1. Implementar lógica TCC
    Escribir lógica TCC en la clase de implementación:
@Service
public class OrderTccServiceImpl implements OrderTccService {
    
    

    @Override
    public boolean tryCreateOrder(OrderDTO orderDTO) {
    
    
        // 预留库存逻辑
        // ...
        return true;
    }

    @Override
    public boolean confirmOrder(OrderDTO orderDTO) {
    
    
        // 确认创建订单逻辑
        // ...
        return true;
    }

    @Override
    public boolean cancelOrder(OrderDTO orderDTO) {
    
    
        // 取消创建订单逻辑
        // ...
        return true;
    }
}
  1. Pruebe el modo TCC
    Escriba casos de prueba para verificar la gestión de transacciones del modo TCC:
@RunWith(SpringRunner.class)
@SpringBootTest
public class OrderTccServiceTest {
    
    

    @Autowired
    private OrderTccService orderTccService;

    @Test
    public void testCreateOrder() {
    
    
        // 创建一个订单
        OrderDTO orderDTO = new OrderDTO();
        // 设置订单信息
        // ...

        orderTccService.createOrder(orderDTO);
    }
}

Ejecute el caso de prueba para observar si la orden se crea correctamente y verifique el registro para confirmar si las fases Try, Confirm y Cancel del modo TCC se ejecutan correctamente.

Integrar el foso que pisó Seata

Aquí hay algunas dificultades que encontré durante el proceso de integración, y puede haber diferencias entre ellas solo como referencia.

La tabla 'ddz.undo_log' no existe

Información de excepción : proceso de error de confirmación de connectionProxy: la tabla 'ddz.undo_log' no existe.
Solución : elimine la tabla de registro que necesita Seata en la fuente de datos; agregue una nueva undo_logtabla en cada fuente de datos.

CREATE TABLE `undo_log` (
  `id` bigint(20) NOT NULL AUTO_INCREMENT,
  `branch_id` bigint(20) NOT NULL,
  `xid` varchar(100) NOT NULL,
  `context` varchar(128) NOT NULL,
  `rollback_info` longblob NOT NULL,
  `log_status` int(11) NOT NULL,
  `log_created` datetime NOT NULL,
  `log_modified` datetime NOT NULL,
  `ext` varchar(100) DEFAULT NULL,
  PRIMARY KEY (`id`),
  UNIQUE KEY `ux_undo_log` (`xid`,`branch_id`)
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8;

no se encontró ningún servicio disponible 'null', asegúrese de que la configuración del registro sea correcta

Información de excepción : la razón de esto es que no cargamos Seata config.txten nacos.
Solución : Ejecute el comando para cargar la configuración en el centro de configuración de Nacos. Consulte lo anterior:把配置文件config.txt加载到nacos上

La transacción distribuida no tiene efecto

Motivo : las múltiples fuentes de datos que utilizamos dynamicno habilitan Seatalas transacciones distribuidas de forma predeterminada.
Solucióndynamic : agregue la configuración en el archivo de configuración yml seata: truepara habilitar las transacciones distribuidas.

la fuente de datos dinámica no puede encontrar la fuente de datos principal

Motivo : Este es un error en la información de configuración de la fuente de datos. El motivo de esta excepción es que soy demasiado descuidado para escribir la conexión de la base de datos (url) incorrectamente.
Solución : vuelva a verificar datasourcela configuración de las siguientes fuentes de datos.

Fallo en el enlace de comunicaciones

Razón : la mayoría de las razones aquí son que MySQL necesita especificar si se debe realizar una conexión SSL, y la conexión SSL está habilitada de manera predeterminada.
Solución : simplemente agréguelo después de la URL de configuración de la conexión a la base de datos &useSSL=false.

Resumir

A medida que los sistemas distribuidos continúan evolucionando, también lo hará el campo de las transacciones distribuidas. En el futuro, podemos explorar más modelos y soluciones de transacciones distribuidas para satisfacer las necesidades de diferentes escenarios comerciales. Al mismo tiempo, Seata, como proyecto activo de código abierto, seguirá introduciendo nuevas funciones y mejoras. Podemos estar atentos a las actualizaciones de la comunidad de Seata y aportar nuestra propia fuerza.

Además, además de Seata, existen otras soluciones de transacciones distribuidas, como TCC-Transaction, SAGA, , HSTCetc. Estas soluciones también merecen nuestro estudio y exploración en profundidad. De acuerdo con diferentes escenarios comerciales, podemos elegir la solución más adecuada para resolver el problema de transacciones distribuidas.

Referencias

Documentación Oficial Nacos Documentación
Oficial Seata Documentación
Oficial Spring Boot

Supongo que te gusta

Origin blog.csdn.net/weixin_45626288/article/details/132155575
Recomendado
Clasificación