Foreword
Seata
Alibaba is distributed transaction middleware, open source, in an efficient and business 0-invasive manner, to solve the problems facing distributed transaction under micro-services scenario.
In fact, the official GitHub
has been given under a variety of environmental Seata
applications sample project, address: https://github.com/seata/seata-samples
.
Why do I want to re-write it again, for two main reasons:
- Official website code example, rely too much confusion as to which what role
- Seata less relevant information, the author in the process of building, encountered some pit, record it
First, prepare the environment
This article relates to the software environment is as follows:
- SpringBoot 2.1.6.RELEASE
- Dubbo 2.7.1
- Mybatis 3.5.1
- 0.6.1 Seat
- Zookeeper 3.4.10
1, business scene
To simplify the process, we only need two orders and inventory services. When creating an order, call the service inventory, inventory deductions.
Tables involved in the design as follows:
CREATE TABLE `t_order` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`order_no` varchar(255) DEFAULT NULL,
`user_id` varchar(255) DEFAULT NULL,
`commodity_code` varchar(255) DEFAULT NULL,
`count` int(11) DEFAULT '0',
`amount` double(14,2) DEFAULT '0.00',
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=38 DEFAULT CHARSET=utf8;
CREATE TABLE `t_storage` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`commodity_code` varchar(255) DEFAULT NULL,
`name` varchar(255) DEFAULT NULL,
`count` int(11) DEFAULT '0',
PRIMARY KEY (`id`),
UNIQUE KEY `commodity_code` (`commodity_code`)
) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8;
复制代码
It also requires a rollback log table:
CREATE TABLE `undo_log` (
`id` bigint(20) NOT NULL AUTO_INCREMENT,
`branch_id` bigint(20) NOT NULL,
`xid` varchar(100) 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,
`context` varchar(100) DEFAULT NULL,
PRIMARY KEY (`id`),
UNIQUE KEY `ux_undo_log` (`xid`,`branch_id`)
) ENGINE=InnoDB AUTO_INCREMENT=67 DEFAULT CHARSET=utf8;
复制代码
2, Seata download and install
Open https://github.com/seata/seata/releases
, the latest version is v0.6.1
.
After downloading unzip to seata-server-0.6.1\distribution\bin
the directory you can see seata-server.bat和seata-server.sh
, choose a double-click execution.
Not surprisingly, then, when you see -Server started ...
other words, it started normally.
3, Maven relies
Because the project is Dubbo, Dubbo we first introduced its dependencies.
<dependency>
<groupId>org.apache.dubbo</groupId>
<artifactId>dubbo</artifactId>
<version>2.7.1</version>
</dependency>
<dependency>
<groupId>org.apache.dubbo</groupId>
<artifactId>dubbo-spring-boot-starter</artifactId>
<version>2.7.1</version>
</dependency>
复制代码
Dubbo service to be registered to Zookeeper, introduced curator client.
<dependency>
<groupId>org.apache.curator</groupId>
<artifactId>curator-framework</artifactId>
<version>2.13.0</version>
</dependency>
<dependency>
<groupId>org.apache.curator</groupId>
<artifactId>curator-recipes</artifactId>
<version>2.13.0</version>
</dependency>
复制代码
Finally, the introduction of Seata.
<dependency>
<groupId>io.seata</groupId>
<artifactId>seata-all</artifactId>
<version>0.6.1</version>
</dependency>
复制代码
Of course, there are other such Mybatis、mysql-connector
like on a non-stick, it can be self-introduction.
Second, the project configuration
1、application.properties
Here only you need to configure the database connection information and information related to Dubbo.
server.port=8011
spring.datasource.url=jdbc:mysql://127.0.0.1:3306/seata
spring.datasource.username=root
spring.datasource.password=root
dubbo.application.name=order-service
dubbo.registry.address=zookeeper://127.0.0.1:2181
dubbo.protocol.name=dubbo
dubbo.protocol.port=20881
dubbo.consumer.timeout=9999999
dubbo.consumer.check=false
复制代码
2, the data source
Seata transaction branch is achieved through a proxy data source, so you need to configure a proxy data source, otherwise the transaction will not be rolled back.
@Bean
public DataSourceProxy dataSourceProxy(DataSource dataSource) {
return new DataSourceProxy(dataSource);
}
复制代码
Note that, where the DataSourceProxy
class is located io.seata.rm.datasource
inside the package.
3, Seata configuration
Also you need to configure a global transaction scanner. There are two parameters, one is the application name, is a group transactions.
@Bean
public GlobalTransactionScanner globalTransactionScanner() {
return new GlobalTransactionScanner("springboot-order", "my_test_tx_group");
}
复制代码
In fact, a series of initial work on Seata transactions are done here.
4, configuration registry
Seata
When connected to the server requires some configuration items, this time there is a registry.conf
file you can specify what registry and configuration files yes.
There are many optional, for example file、nacos 、apollo、zk、consul
.
The back four is a mature industry configuration registry product, why there is a file it?
The official intention is not to rely on third parties to configure rapid integration testing on the basis of registry seata
function, but the file
type itself does not have the dynamic discovery and dynamic configuration capabilities registry.
registry.conf
Document reads as follows:
registry {
type = "file"
file {
name = "file.conf"
}
}
config {
# file、nacos 、apollo、zk、consul
type = "file"
file {
name = "file.conf"
}
}
复制代码
If you choose the file
type, the name attribute specifies file.conf
, this file is specified in the configuration information of the client or server. For example the transport protocol, server address.
service {
#vgroup->rgroup
vgroup_mapping.my_test_tx_group = "default"
#only support single node
default.grouplist = "127.0.0.1:8091"
#degrade current not support
enableDegrade = false
#disable
disable = false
}
复制代码
Third, the business code
1. Inventory Service
In the inventory service, to get the commodity code and the total number of purchase, the deduction can be.
<update id="decreaseStorage">
update t_storage set count = count-${count} where commodity_code = #{commodityCode}
</update>
复制代码
Dubbo will then deduct inventory service interfaces to expose.
2, order service
In order service, the first deduct inventory, then create an order. Finally, an exception is thrown, then go to the database to check whether the transaction is rolled back.
@GlobalTransactional
public void createOrder(OrderDTO orderDTO) {
System.out.println("开始全局事务。XID="+RootContext.getXID());
StorageDTO storageDTO = new StorageDTO();
storageDTO.setCount(orderDTO.getCount());
storageDTO.setCommodityCode(orderDTO.getCommodityCode());
//1、扣减库存
storageDubboService.decreaseStorage(storageDTO);
//2、创建订单
orderDTO.setId(order_id.incrementAndGet());
orderDTO.setOrderNo(UUID.randomUUID().toString());
Order order = new Order();
BeanUtils.copyProperties(orderDTO,order);
orderMapper.createOrder(order);
throw new RuntimeException("分布式事务异常..."+orderDTO.getOrderNo());
}
复制代码
It is noteworthy that, in the beginning of the transaction order service method, need to mark @GlobalTransactional
. In addition, the service's inventory method, do not need this comment, the transaction will be spread through Dubbo.
IV Notes
1, data source
Remember, Seata transaction branch is achieved through a proxy data source, you must not forget to configure the data source agency.
2, the primary key increment
In the database, the table is the primary key ID from the growing fields. If your field is not incremented, then in the Mybatis insert SQL
, the column name you want to write complete.
For example, we can write SQL:
INSERT INTO table_name VALUES (值1, 值2,....)
复制代码
So this time it should be written as:
INSERT INTO table_name (列1, 列2,...) VALUES (值1, 值2,....)
复制代码
3, serialization problem
In the order, the amount
field type double
. In the seata0.6.1
release, the default serialization way fastjson
, but it will be serialized into this field bigdecimal
type, can cause back type mismatch.
But in a subsequent seata0.7.0
version (not yet released), it has been the default serialization changed to jackson
.
But no need to worry, this is generally not a problem. The author is a mistake because the lead pack, which leads to find the problem.
4, the code for this article
Sample code in this https://github.com/taoxun/springboot-dubbo-zookeeper-seata
article: .
5. Other
Welcomed the timely exchange of questions -