Five minute experience of distributed transaction framework Seata

seata is an open source distributed transaction solution, which is committed to providing high-performance and easy-to-use distributed transaction services. seata will provide users with AT, TCC, SAGA and XA transaction modes to create a one-stop distributed solution for users. This tutorial aims to provide readers with a quick start case of seata. Please refer to the official cases and documents for detailed use.

Seata server setup

In Seata, the transaction manager is a separate service, which can be used out of the box without secondary development. Download address https://github.com/seata/seata/releases . The version 2.1.0 is used in this case. After downloading and decompressing, you need to configure the Seata server and configure the file in the conf directory Conf and registry conf.

Where file Conf is a data storage method for configuring Seata server, which supports local documents and databases. This paper directly uses local file storage. The configuration is as follows:

## transaction log store, only used in seata-server
store {
  ## store mode: file,db
  mode = "file"

  ## file store property
  file {
    ## store location dir
    dir = "sessionStore"
    # branch session size , if exceeded first try compress lockkey, still exceeded throws exceptions
    maxBranchSessionSize = 16384
    # globe session size , if exceeded throws exceptions
    maxGlobalSessionSize = 512
    # file buffer size , if exceeded allocate new buffer
    fileWriteBufferCacheSize = 16384
    # when recover batch read size
    sessionReloadReadSize = 100
    # async, sync
    flushDiskMode = async
  }

  ## database store property
  db {
    ## the implement of javax.sql.DataSource, such as DruidDataSource(druid)/BasicDataSource(dbcp) etc.
    datasource = "druid"
    ## mysql/oracle/postgresql/h2/oceanbase etc.
    dbType = "mysql"
    driverClassName = "com.mysql.jdbc.Driver"
    url = "jdbc:mysql://127.0.0.1:3306/seata"
    user = "mysql"
    password = "mysql"
    minConn = 5
    maxConn = 30
    globalTable = "global_table"
    branchTable = "branch_table"
    lockTable = "lock_table"
    queryLimit = 100
    maxWait = 5000
  }
}

registry.conf is used to configure the registry of Seata server. This case is registered on eureka.

registry {
  # file ,nacos ,eureka,redis,zk,consul,etcd3,sofa
  type = "eureka"

  nacos {
    application = "seata-server"
    serverAddr = "localhost"
    namespace = ""
    cluster = "default"
    username = ""
    password = ""
  }
  eureka {
    serviceUrl = "http://localhost:8761/eureka"
    application = "default"
    weight = "1"
  }
  
  ...
 }

Business code initialization

go Official website To download the code, you can also go to the case sorted out in this article. Download address: https://github.com/forezp/distributed-lab/tree/master/seata-sample

Project introduction

After downloading, the file directory of the project project is as follows. There are five projects, namely eureka (Registration Center), business (transaction service), storage (inventory service), order (order service) and account (account service). Seata server and the other four business services need to be registered with eureka. The sql directory is the script for initializing sql. The directory structure of the project is as follows.

seata-sample
├── account
├── bussiness
├── eureka
├── order
├── pom.xml
├── sql
└── storage

Initialize sql

Create the database of seata in the database and import the database script in the sql directory.

Configuration change

After introducing the sdk of seata into the business code, you need to configure file Conf and registry Conf, please check the code in the source code. In application Configure mysql connection in properties:

spring.cloud.alibaba.seata.tx-service-group=my_test_tx_group
spring.datasource.url=jdbc:mysql://127.0.0.1:3306/seatatest?useSSL=false&serverTimezone=UTC
spring.datasource.username=root
spring.datasource.password=123456

Start project

Start the Seata server, euraka, business, storage, order and account projects successively. Address to access eureka: http://localhost:8761/ , you can see that all services are registered with eureka.

When the business service is started, the following data will be inserted into the database:

 @PostConstruct
    public void initData() {
        jdbcTemplate.update("delete from account_tbl");
        jdbcTemplate.update("delete from order_tbl");
        jdbcTemplate.update("delete from storage_tbl");
        jdbcTemplate.update("insert into account_tbl(user_id,money) values('U100000','10000') ");
        jdbcTemplate.update("insert into storage_tbl(commodity_code,count) values('C100000','200') ");
    }

test

seata officials have written the code logic and can test it directly.

curl http://127.0.0.1:8084/purchase/commit

The interface code logic is as follows:

 @RequestMapping(value = "/purchase/commit", produces = "application/json")
    public String purchaseCommit() {
        try {
            businessService.purchase("U100000", "C100000", 30);
        } catch (Exception exx) {
            return exx.getMessage();
        }
        return "Global transaction commit";
    }

That is, buy 30 inventories. The current inventory and amount are enough, so the transaction is normal.

After that, you can see the account in the database_ The money with id 1 of TBL will be reduced by 5 and order_ A new record, storage, will be added in TBL_ The count field with id 1 of TBL is reduced by 1

2020-05-21 16:09:12.388 INFO [AsyncCommitting_1]io.seata.server.coordinator.DefaultCore.doGlobalCommit:240 -Committing global transaction is successfully done, xid = 10.66.40.141:8091:2012236512.

Transaction rollback with exception

Call the following interfaces:

curl http://127.0.0.1:8084/purchase/rollback

The interface code logic is as follows:

@RequestMapping("/purchase/rollback")
    public String purchaseRollback() {
        try {
            businessService.purchase("U100000", "C100000", 99999);
        } catch (Exception exx) {
            return exx.getMessage();
        }
        return "Global transaction commit";
    }

The secondary interface first deducts the inventory, then deducts the money, and finally queries the database and finds that the inventory in the database is negative, so an exception is thrown and rollback occurs. After completion, the data in the database does not change, and the rollback succeeds. It can be seen that the distributed transaction rollback operation succeeded.

reference material

http://seata.io/zh-cn/docs/overview/what-is-seata.html

Added by wrathican on Thu, 06 Jan 2022 11:21:43 +0200