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
- Spring Cloud of actual combat | first article: Windows setup Nacos services
- The second Spring Cloud of actual combat | : Spring Cloud integration Nacos registry
- Spring Cloud of actual combat | article 3: the Spring Cloud integration Nacos configuration center
- Spring Cloud of actual combat | article 4: Spring Cloud integration Gateway API Gateway
- Spring Cloud of actual combat | article 5: Spring Cloud integration OpenFeign between micro service calls
- Spring Cloud of actual combat | article 6: the Spring Cloud + Spring Security Gateway OAuth2 + JWT micro service unified certificate authority
- 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
- 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
- Spring Cloud of actual combat | the nine article: Spring Security OAuth2 authentication server unified authentication custom exception handling
Management of the front
- Vue – element – admin combat | first article: remove the mock access background, building a youlai – mall to mall before and after the separation management platform
- Vue – element – the second admin combat | : minimal change access backend implementation according to the dynamic loading menu
Wechat applets
- 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
- 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
- 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 Seata
spring-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_group
Configure a transaction group, in which the group name is specifiedmall_tx_group
Need to configure the serverservice.vgroupMapping.mall_tx_group=default
consistentenable-auto-data-source-proxy: true
The proxy data source is automatically enabled for Seata to integrate operations on the UNdo_log tablenamespace: seata_namespace_id
Seata – servergroup: SEATA_GROUP
Seata – 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.