Solution to distributed transaction - seata

Recommended - seata

Official website: https://seata.io/zh-cn/

Seata currently has three distributed transaction implementation schemes: AT, TCC and SAGA

  • AT mode mainly focuses on the data consistency of multi DB access. Of course, it also includes the 2PC improvement of multi DB data access consistency under multi services
  • TCC mode mainly focuses on business splitting and solves the consistency of calls between microservices when expanding resources horizontally according to business
  • Saga mode is a long transaction solution provided by SEATA. In Saga mode, each participant in the business process submits local transactions
    When a participant fails, it compensates the previous successful participants. Both the phase I forward service and the phase II compensation service are available
    Implemented by business development.

Use of seata

###1. Installing and deploying Seata

Step 1: Download: https://github.com/seata/seata/releases

Baidu cloud disk:
Link: https://pan.baidu.com/s/1Fkzf-FZNruRHe7VEibI4Jg
Extraction code: zycx

Step 2: unzip seata-server-0.9 0

Step 3: run Seata server under bin bat

2. Adding tables to databases involving distributed transactions

seata needs to provide a table in each resource server:
This table is mainly used for distributed transaction logging. The table is located in seata service:

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=12 DEFAULT CHARSET=utf8

3. Case view

####3.1 unzip the case in the data and open it

####3.2 brief description of distributed transaction business case

If the dormitory is switched, the male dormitory becomes the female dormitory and the female dormitory becomes the male dormitory, the dormitory number corresponding to the employee's accommodation should also be changed.

####3.3 introduction to Seata custom SpringBootStarter

First, specify the configuration method of seata

In file Note the default port of seata service in conf

####3.4 explanation of main configuration
In fact, we can find that seata is very simple to use. We only need to use the data source provided by seata and name each RM resource server.

package com.itheima.seata.config;

import com.alibaba.druid.pool.DruidDataSource;
import io.seata.rm.datasource.DataSourceProxy;
import io.seata.spring.annotation.GlobalTransactionScanner;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Primary;
import org.springframework.core.env.Environment;

import javax.sql.DataSource;

//@Configuration
public class DataSourceConfig {

    /**
     * Create a database connection pool object, which can be any type of database connection pool object
     * @return
     */
    @Bean
    @ConfigurationProperties(prefix = "spring.datasource")
    public DruidDataSource ds0(){
        DruidDataSource druidDataSource = new DruidDataSource();
        return druidDataSource;
    }

    /**
     * Wrap the above database connection pool object into the database connection pool object of Alibaba seata
     * @Primary Indicates that when multiple objects of the same type appear, it is used on the preferred object
     * @param dataSource
     * @return
     */
    @Primary
    @Bean
    public DataSource dataSource(DruidDataSource dataSource){
        DataSourceProxy dsp = new DataSourceProxy(dataSource);
        return dsp;
    }

    @Bean
    public GlobalTransactionScanner globalTransactionScanner(Environment environment) {
        //Transaction group name
        String applicationName = environment.getProperty("spring.application.name");
        String groupName = environment.getProperty("seata.group.name");
        if (applicationName == null) {
            return new GlobalTransactionScanner(groupName == null ? "my_test_tx_group" : groupName);
        } else {
            return new GlobalTransactionScanner(applicationName, groupName == null ? "my_test_tx_group" : groupName);
        }
    }


}

####3.5 turn seata service into starter

####3.6 import Seata spring boot starter into each RM resource server and test again

Keep in mind that the @ GlobalTransactional annotation needs to be added to the main business method

As shown in the figure:

Again, different services link different databases, and transactions can be controlled together, meeting the characteristics of distributed transactions

Distributed transaction solution: Message final consistency

The ultimate message consistency should be the most used in the industry. Its core idea is to split distributed transactions into local transactions for processing. This idea comes from ebay. We can see some details from the following flow chart:

The basic idea is:

The message producer needs to create an additional message table and record the message sending status. Message tables and business data should be submitted in a transaction, that is, they should be in a database. The message is then sent through MQ to the consumer of the message. If the message fails to be sent, it will be sent again.

The message consumer needs to process the message and complete its own business logic. At this time, if the local transaction processing is successful, it indicates that the processing has been successful. If the processing fails, the execution will be retried. If it is a business failure, you can send a business compensation message to the manufacturer to notify the manufacturer to roll back and other operations.

The producer and consumer scan the local message table regularly and send the unfinished messages or failed messages again. If there is reliable automatic reconciliation and account supplement logic, this scheme is still very practical.

This scheme follows the BASE theory and adopts the final consistency, which is more suitable for the actual business scenario, that is, there will be no complex implementation like 2PC (when the call chain is very long, the availability of 2PC is very low), and there may be no confirmation or roll back failure like TCC.

Advantages: a very classic implementation avoids distributed transactions and achieves final consistency.
Disadvantages: Message tables are coupled to business systems.

4. seata is used in the project

####4.1 install Seata spring boot starter and its parent project

Ensure that the local repository has the jar package of Seata spring boot starter and the jar package of the parent project

####4.2 using seata distributed transactions in the project

Step 1: add seata log table in leyou database

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=16 DEFAULT CHARSET=utf8

Step 2: import Seata spring boot starter into all RM resource microservices that require distributed transactions

Order module

Commodity module

Step 3: add @ GlobalTransactional annotation in the main business method

Step 4: add a configuration file in all RM resource microservices

Step 5: restart the test

Note that there is a pit here: you can figure out the database connection pool provided by seata with your hair. Ali does not provide Java util. The JDBC type corresponding to date.

Problem solving: add dependencies and annotations

<dependencies>
    <dependency>
        <groupId>org.mybatis</groupId>
        <artifactId>mybatis</artifactId>
        <version>3.5.2</version>
        <scope>compile</scope>
    </dependency>
</dependencies>

Add an annotation on the attribute that needs to specify the JDBC type, that is, two dates need to be annotated

spring:
  application:
    name: order-service
  datasource:
    url: jdbc:mysql://127.0.0.1:3306/leyou?useUnicode=true&characterEncoding=UTF-8&serverTimezone=GMT%2B8&useSSL=false
    username: root
    password: root
    driver-class-name: com.mysql.jdbc.Driver

Distributed transaction solution: MQ transaction messages

The MQ solution requires this type of MQ to be able to perform transactions with transaction messages; At present, only RocketMQ can do it, so MQ in MQ based distributed transaction solutions refers to RocketMQ.

RocketMQ realizes the atomicity, consistency and reliability of local transactions and MQ messages through transactional messages; The processing of remote transactions is guaranteed as far as possible (in the above case, the operation of order generation is 100% successful as far as possible). If the processing fails, manual intervention is still required

Keywords: Java Distribution Transaction

Added by birwin on Sat, 01 Jan 2022 22:48:07 +0200