Seata distributed transaction online experience address: www.youlai.store

github.com/hxrui/youla…

If you want to join the open source project, please contact me (wechat id: Haoxianrui). I hope we can exchange and learn together. I think the project is helpful to you and hope to give you a star or attention.

A preface.

I believe that those who have learned about the open source project Youlai-Mall should know that this project is mainly based on Spring Cloud + Vue and other latest and most mainstream technologies to implement a set of micro service architecture + front and back end separation of the full stack mall system (App, wechat small programs, etc.).

Links to previous articles:

Micro service

  1. Spring Cloud of actual combat | first article: Windows setup Nacos services
  2. The second Spring Cloud of actual combat | : Spring Cloud integration Nacos registry
  3. Spring Cloud of actual combat | article 3: the Spring Cloud integration Nacos configuration center
  4. Spring Cloud of actual combat | article 4: Spring Cloud integration Gateway API Gateway
  5. Spring Cloud of actual combat | article 5: Spring Cloud integration OpenFeign between micro service calls
  6. Spring Cloud of actual combat | article 6: the Spring Cloud + Spring Security Gateway OAuth2 + JWT micro service unified certificate authority
  7. Spring Cloud of actual combat | the seven articles: Spring Cloud + Spring Security Gateway OAuth2 integrated unified certificate authority platform to realize the logout disable JWT scheme
  8. Spring Cloud of actual combat | the eight: Spring Cloud + Spring Security OAuth2 + Vue no refresh perception to realize the separation mode before and after JWT renewed
  9. Spring Cloud of actual combat | the nine article: Spring Security OAuth2 authentication server unified authentication custom exception handling

Management of the front

  1. Vue – element – admin combat | first article: remove the mock access background, building a youlai – mall to mall before and after the separation management platform
  2. Vue – element – the second admin combat | : minimal change access backend implementation according to the dynamic loading menu

Wechat applets

  1. Vue + uniapp mall real | first article: 【 】 has to store WeChat small programs to rapidly develop access Spring Cloud OAuth2 authentication center to complete the authorization to log in

Deployment of article

  1. Docker combat | article 2: a key to achieve IDEA integration Docker plug-in automatic packaging deployment service project, once and for all the technology is worth a try
  2. Docker combat | article 3: Docker to install Nginx, implementation is based on the vue – element – admin deployment project to build the framework of line

When it comes to microservices, naturally distributed transactions are necessary to ensure data consistency between services. Therefore, this article will illustrate how Seata’s AT mode is applied in the actual scene of microservices, hoping that we can have a look AT its shape to know its meaning.

1. Requirement description

The member submits the order, deducts the goods inventory, increases the membership points, completes the previous steps, changes the order status to completed.

According to the demand, it can be seen that this involves three micro-services, namely order, commodity and membership, which respectively correspond to the mum-OMS, mum-PMS and mum-UMS micro-services of YouLai-mall project.

2. Technical version

technology version instructions
Spring Cloud Hoxton.SR9 Microservices Architecture
Nacos 1.4.0 Register and configure the center
Seata 1.4.1 Distributed transaction

3. Environment preparation

3.1 Nacos Installation and Configuration

www.cnblogs.com/haoxianrui/…

Go to the Nacos console and create the SeATA namespace

Remember that the namespace ID is customized to seatA_namespace_id, as required later

3.2 Seata database creation

Create a database named Seata and execute the MySQL database script provided in the Github source for Seata

MySQL script address: github.com/seata/seata…

Seata-server installation

Important disclaimer: 192.168.1.188 is the IP address of the VIRTUAL machine where Nacos and Seata are installed

Click the Docker Hub link to check out the latest version of Seata

You can see that the latest version is 1.4.1, copy command to obtain the latest version image

Docker pull seataio/seata - server: 1.4.1Copy the code

Start temporary container

docker run -d --name seata -p 8091:8091 seataio/seata-server
Copy the code

Get the registry. Conf configuration file from the temporary container

mkdir /opt/seata
docker cp seata:/seata-server/resources/registry.conf  /opt/seata
Copy the code

Modify the registry. Conf configuration, set the type to nacos, and namesapce to the id of the namespace created in nacOS above, namely, seatA_namespace_id.

vim /opt/seata/registry.conf
Copy the code
registry { type = "nacos" loadBalance = "RandomLoadBalance" loadBalanceVirtualNodes = 10 nacos { application = "Seata-server" serverAddr = "192.168.1.188:8848" Namespace = "seatA_namespace_id" group = "SEATA_GROUP" cluster = "Default"}} config {type = "nacos" nacos {serverAddr = "192.168.1.188:8848" Namespace = "seatA_namespace_id" group =  "SEATA_GROUP" } }Copy the code

After registry. Conf is arranged, delete the temporary container

docker rm -f seata
Copy the code

Start pushing the Seata dependency configuration to Nacos

Get configuration files (config.txt) and push scripts (nacos/nacos-config.sh) from Seata’s GitHub source.

Address: github.com/seata/seata…

Because of the script, the file is stored in the following directory

/ opt/seata ├ ─ ─config.txt └── imp -config.sh
Copy the code

Modify the configuration file config.txt

vim /opt/seata/config.txt
Copy the code

Modify the connection information of the transaction group and MySQL as follows:

service.vgroupMapping.mall_tx_group=default

store.mode=db
store.db.driverClassName=com.mysql.cj.jdbc.Driver
store.db.url=jdbc:mysql://www.youlai.store:3306/seata?useUnicode=true&rewriteBatchedStatements=true
store.db.user=root
store.db.password=123456
Copy the code

Execute push command

CD /opt/seata/nacos bash nacos-config.sh -h 192.168.1.188 -p 8848 -g SEATA_GROUP -t seatA_namespace_id -u nacos -w nacosCopy the code
  • -t seatA_namespace_id Specifies the ID of the Nacos configuration namespace
  • -g SEATA_GROUP Specifies the name of the Nacos configuration group

If init nacos config fail is displayed, check the modification information. If failure is displayed, modify the properties in config. TXT.

RRGz1B7MUP: No such file or directory do not panic if an error such as cat: / TMP /tmp.rRGz1B7MUP: No such file or directory occurs.

After the push is complete, go to the Nacos console to check whether the configuration has been added successfully

With that done, the final step is to start the Seata container

Docker run -d --name seata --restart=always -p 8091:8091 \ -e SEATA_IP=192.168.1.188 \ -e SEATA_CONFIG_NAME=file:/seata-server/resources/registry.conf \ -v /opt/seata/registry.conf:/seata-server/resources/registry.conf \ -v /opt/seata/logs:/root/logs \ seataio/seata-serverCopy the code

Seata client

The previous section completed the Seata server application installation, adding the Seata configuration to the Nacos configuration center, and registering Seata to the Nacos registry.

The next step is to configure the client and associate the three microservices of order (mall- OMS), commodity (mall- PMS) and membership (mall- UMS) with Seata-Server through relevant configuration.

1. Add the undo_log table

In THE AT mode of Seata, transactions are directly committed in the first phase because an UNdo_log table needs to be created in each RM to record data snapshots before and after service execution.

If you need to roll back data in phase 2, you can directly roll back data based on the undo_log table. If the rollback is successful, snapshot data is deleted in phase 2.

Seata Github source library undo_log table undo_log

Github.com/seata/seata…

Note the comment on the first line

-- for AT mode you must to init this sql for you business database. the seata server not need it.
CREATE TABLE IF NOT EXISTS `undo_log`
(
    `branch_id`     BIGINT(20)   NOT NULL COMMENT 'branch transaction id',
    `xid`           VARCHAR(100) NOT NULL COMMENT 'global transaction id',
    `context`       VARCHAR(128) NOT NULL COMMENT 'undo_log context,such as serialization',
    `rollback_info` LONGBLOB     NOT NULL COMMENT 'rollback info',
    `log_status`    INT(11)      NOT NULL COMMENT '0:normal status,1:defense status',
    `log_created`   DATETIME(6)  NOT NULL COMMENT 'create datetime',
    `log_modified`  DATETIME(6)  NOT NULL COMMENT 'modify datetime',
    UNIQUE KEY `ux_undo_log` (`xid`, `branch_id`)
) ENGINE = InnoDB
  AUTO_INCREMENT = 1
  DEFAULT CHARSET = utf8 COMMENT ='AT transaction mode undo table';
Copy the code

Execute the script to create the undo_log table in the three databases of the mall- OMS, mall- PMS, and mall- UMS

2. Add dependencies

Add the following SEATA client dependencies for the mall- OMS, mall- PMS, and mall- UMS microservices of Youlai-mall respectively

< the dependency > < groupId > IO. Seata < / groupId > < artifactId > seata - spring - the boot - starter < / artifactId > < version > 1.4.0 < / version > </dependency> <dependency> <groupId>com.alibaba.cloud</groupId> <artifactId>spring-cloud-starter-alibaba-seata</artifactId> <exclusions> <! --> <exclusion> <groupId> IO. Seata </groupId> <artifactId>seata-all</artifactId> </exclusion> <exclusion> <groupId>io.seata</groupId> <artifactId>seata-spring-boot-starter</artifactId> </exclusion> </exclusions> </dependency> <dependency> <groupId> IO. Seata </groupId> <artifactId>seata-all</artifactId> <version>1.4.1</version> </dependency> <dependency> <groupId>io.seata</groupId> <artifactId>seata-spring-boot-starter</artifactId> The < version > 1.4.1 < / version > < / dependency >Copy the code
  • Use the Spring Cloud officially provided by Alibaba and the Spring Boot initiator integrated by Seataspring-cloud-starter-alibaba-seata
  • You need to specify that the SEATA version is consistent with the service version, in this case 1.4.1

3. Yml configuration

Seata Github source library Spring configuration link:

Github.com/seata/seata…

The configuration is simplified as follows:

Seata: tx-service-group: mall_tx_group enable-auto-data-source-proxy: true registry: type: nacos nacos: server-addr: localhost:8848 namespace: seata_namespace_id group: SEATA_GROUP config: type: nacos nacos: server-addr: localhost:8848 namespace: seata_namespace_id group: SEATA_GROUPCopy the code
  • tx-service-group: mall_tx_groupConfigure a transaction group, in which the group name is specifiedmall_tx_groupNeed to configure the serverservice.vgroupMapping.mall_tx_group=defaultconsistent
  • enable-auto-data-source-proxy: trueThe proxy data source is automatically enabled for Seata to integrate operations on the UNdo_log table
  • namespace: seata_namespace_idSeata – server
  • group: SEATA_GROUPSeata – server

Place the thin configuration in the configuration file of the mall- OMS, mall- PMS, and mall- UMS respectively

4. Start class adjustment

Because you are using the proxy data source provided by Seata, remove the data source that SpringBoot automatically assembs by default in the boot class

It also needs to be adjusted separately in the three microservice startup classes, otherwise the distributed transaction will not take effect

@SpringBootApplication(exclude = DataSourceAutoConfiguration.class)
Copy the code

Four. Test environment simulation

After the Seata service installation and client configuration are completed according to the appeal steps

Next comes the work of looking beyond the surface, creating business tables and writing business code based on business requirements

Table 1. The business

To provide the key fields of the business table, click Youlai-mall for complete table structure

Order list (oms_order) :

CREATE TABLE `oms_order` ( `id` bigint NOT NULL AUTO_INCREMENT COMMENT 'id', `status` int NOT NULL DEFAULT '101' COMMENT Order Status [101-> Waiting for payment; 102-> User cancelled; 103-> System cancelled; 201-> Paid; 202-> Requested refund; 203-> Refunded; 301-> Waiting for shipment; 401-> Shipped; 501-> User received; 502-> System received; 901-> Completed], PRIMARY KEY (' id ') USING BTREE) ENGINE=InnoDB DEFAULT CHARSET= UTf8MB4 COLLATE= UTf8MB4_0900_ai_CI COMMENT=' table ';Copy the code

The inventory table (pms_sku) :

CREATE TABLE 'pMS_sku' (' id' bigint NOT NULL AUTO_INCREMENT COMMENT 'increment ', 'stock' int NOT NULL DEFAULT '0' COMMENT 'stock ', PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci ROW_FORMAT=DYNAMIC COMMENT=' inventory table ';Copy the code

The member table (ums_user) :

CREATE TABLE `ums_user` ( `id` bigint NOT NULL AUTO_INCREMENT, 'username' varchar(64) CHARACTER SET utf8 COLLATE UTf8_general_ci NOT NULL, 'point' int DEFAULT '0' COMMENT 'iD ', PRIMARY KEY (' id ') USING BTREE) ENGINE=InnoDB DEFAULT CHARSET= UTf8MB4 ROW_FORMAT=DYNAMIC COMMENT=' member info ';Copy the code

2. Business code

Provide the core business code, please click Youlai-mall for the complete code

Order microservice (mall-OMS) :

Code location: OmsOrderServiceImpl# Submit

@override @GlobalTransactional(rollbackFor = exception.class) public Boolean submit() {log.info(" reduce inventory ----begin"); productFeignService.updateStock(1l, -1); Log.info (" subtract inventory ----end"); Log.info (" add credits ----begin"); memberFeignService.updatePoint(1l, 10); Log.info (" add credits ----end"); Log.info (" Change order status ----begin"); boolean result = this.update(new LambdaUpdateWrapper<OmsOrder>().eq(OmsOrder::getId, 1l).set(OmsOrder::getStatus, 901)); Log.info (" modify order status ----end"); return result; }Copy the code
  • The @GlobalTransactional annotation marks TM (transaction manager) for enabling global transactions

Mall – PMS:

AppSkuController#updateStock

@PutMapping("/{id}/stock")
public Result updateStock(@PathVariable Long id, @RequestParam Integer num) {
    PmsSku sku = iPmsSkuService.getById(id);
    sku.setStock(sku.getStock() + num);
    boolean result = iPmsSkuService.updateById(sku);
    return Result.status(result);
}
Copy the code

Mall-ums Membership:

 @PutMapping("/{id}/point")
public Result updatePoint(@PathVariable Long id, @RequestParam Integer num) {
    UmsUser user = iUmsUserService.getById(id);
    user.setPoint(user.getPoint() + num);
    boolean result = iUmsUserService.updateById(user);
    try {
        Thread.sleep(15 * 1000);
    } catch (InterruptedException e) {
        e.printStackTrace();
    }
    return Result.status(result);
}
Copy the code

Thread.sleep(15 * 1000); Simulate a timeout exception to verify that the transaction can be rolled back properly

Note that the setting of 15s is exquisite

Let’s take a look at the feign call configuration for the order microservice,

ribbon:
  ReadTimeout: 10000
Copy the code

Feign uses the ribbon for load balancing and remote calls. The ribbon timeout is set to 10s

However, when the order calls the member service, it takes at least 15s to get the result, which will obviously cause the exception of the interface request timeout. Then it depends on whether the transaction can be rolled back normally.

5. Validation tests

This source code including test cases have been integrated into youlai-Mall, you can build a local environment debugging, the project from scratch to build reference project description document.

But if you want to quickly validate Seata distributed transactions and see the results, ok, it satisfies you, in the project added a lab menu, planned for technical point testing, also convenient to provide a complete test environment for everyone.

Without further ado, look at the interface renderings:

After looking at the points highlighted in the diagram above, let’s test distributed transactions through the interface

First, make sure that the pre-order submission will definitely be abnormal due to the timeout of the member points service

  • Closing transaction commits

You can see that in the case of the closed transaction commit order exception, the inventory and credits update succeeded, while the order update failed

Now, what happens when you turn on the transaction commit?

  • Start transaction commit

Failed to update the order status because a global transaction was enabled, causing the updated inventory and credits to be rolled back to the original state.

6. Conclusion

Above, the case of Seata distributed transaction combined with the actual scenario application is integrated and tested. Finally, it can be seen that the final data consistency of the microservice invocation chain is realized through Seata. Finally, we provide the online experience laboratory function module, you can pull to the local and then breakpoint debugging and monitoring data table data changes, I believe that you will soon master the implementation process and implementation principle of Seata.

Finally, if you think the project is good or helpful to you, I hope you can give me a STAR.