With the rapid development of business, application single architecture exposes many problems such as poor code maintainability, low fault tolerance rate, difficult testing and poor agile delivery ability, and so on. On the one hand, the birth of microservices solves the above problems, but on the other hand, it introduces new problems, one of which is how to ensure the consistency of business data among microservices.
This article will take a look at how Fescar can ensure data consistency in a commodity procurement business under Dubbo’s microservices architecture. In the example described in this article, the registration configuration service centers for both Dubbo and Fescar use Nacos. Fescar 0.2.1+ began to support Nacos registration configuration service centers.
Business description
The business of purchasing goods by users includes three micro-services:
- Inventory service: Deducts the amount of inventory for a given item.
- Order service: Generates orders based on purchase requests.
- Account service: user account amount deduction.
The business structure diagram is as follows:
Inventory Service (StorageService)
public interface StorageService {
/**
* deduct storage count
*/
void deduct(String commodityCode, int count);
}
Copy the code
OrderService (OrderService)
public interface OrderService { /** * create order */ Order create(String userId, String commodityCode, int orderCount); }Copy the code
AccountService
public interface AccountService {
/**
* debit balance of user's account
*/
void debit(String userId, int money);
}Copy the code
Note: The three microservices are deployed independently.
8 steps to achieve data consistency
Step 1: Initialize MySQL database (InnoDB storage engine required)
In the resources/JDBC. The properties change StorageService, OrderService, AccountService corresponding connection information.
jdbc.account.url=jdbc:mysql://xxxx/xxxx
jdbc.account.username=xxxx
jdbc.account.password=xxxx
jdbc.account.driver=com.mysql.jdbc.Driver
# storage db config
jdbc.storage.url=jdbc:mysql://xxxx/xxxx
jdbc.storage.username=xxxx
jdbc.storage.password=xxxx
jdbc.storage.driver=com.mysql.jdbc.Driver
# order db config
jdbc.order.url=jdbc:mysql://xxxx/xxxx
jdbc.order.username=xxxx
jdbc.order.password=xxxx
jdbc.order.driver=com.mysql.jdbc.Driver
Copy the code
Step 2: Create the undo_log table (for Fescar AT mode) and related service tables
You can obtain the related table creation script from resources/ SQL /. Run the service table creation script in dubbo_biz. SQL in the corresponding database and run the undo_log. SQL table creation script in each database.
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,
PRIMARY KEY (`id`),
KEY `idx_unionkey` (`xid`,`branch_id`)
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8;
DROP TABLE IF EXISTS `storage_tbl`;
CREATE TABLE `storage_tbl` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`commodity_code` varchar(255) DEFAULT NULL,
`count` int(11) DEFAULT 0,
PRIMARY KEY (`id`),
UNIQUE KEY (`commodity_code`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
Copy the code
DROP TABLE IF EXISTS `order_tbl`;
CREATE TABLE `order_tbl` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`user_id` varchar(255) DEFAULT NULL,
`commodity_code` varchar(255) DEFAULT NULL,
`count` int(11) DEFAULT 0,
`money` int(11) DEFAULT 0,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
DROP TABLE IF EXISTS `account_tbl`;
CREATE TABLE `account_tbl` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`user_id` varchar(255) DEFAULT NULL,
`money` int(11) DEFAULT 0,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
Copy the code
Note: Ensure that each physical library contains the undo_log table. Here, a physical library can be used to represent the independent logical libraries corresponding to the above three microservices.
Step 3: Introduce POM dependencies related to Fescar, Dubbo and Nacos
< the properties > < fescar. Version > 0.2.1 < / fescar version > < dubbo. Alibaba. Version > 2.6.5 < / dubbo. Alibaba. Version > < dubbo registry. Nacos. Version > hundreds < / dubbo. Registry. Nacos. Version > < / properties > < the dependency > <groupId>com.alibaba.fescar</groupId> <artifactId>fescar-spring</artifactId> <version>${fescar.version}</version> </dependency> <dependency> <groupId>com.alibaba.fescar</groupId> <artifactId>fescar-dubbo-alibaba</artifactId> <version>${fescar.version}</version> <exclusions> <exclusion> <artifactId>dubbo</artifactId> <groupId>org.apache.dubbo</groupId> </exclusion> </exclusions> </dependency> <dependency> <groupId>com.alibaba</groupId> <artifactId>dubbo</artifactId> <version>${dubbo.alibaba.version}</version> </dependency> <dependency> <groupId>com.alibaba</groupId> <artifactId>dubbo-registry-nacos</artifactId> <version>${dubbo.registry.nacos.version}</version> </dependency>Copy the code
Description: Due to the current compatibility issues between Apache-Dubbo and Dubbo-Registry – NACos JAR, it is necessary to exclude the apache.dubbo dependency in Fescar-dubbo and manually introduce Alibaba-Dubbo. Subsequent Apache-Dubbo (2.7.1+) will be compatible with Dubbo-Registry – nacOS. In Fescar, the Fescar-Dubbo jar supports apache.dubbo, and the Fescar-Dubbo-Alibaba jar supports Alibaba-Dubbo.
Step 4: Configure the micro service Provider Spring
Configure the three microservice Spring configuration files (dubbo-account-service. XML, dubbo-order-service, and dubbo-storage-service. XML) as follows:
-
Configure the Fescar proxy data source
<bean id="accountDataSourceProxy" class="com.alibaba.fescar.rm.datasource.DataSourceProxy"> <constructor-arg ref="accountDataSource"/> </bean> <bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate"> <property name="dataSource" ref="accountDataSourceProxy"/> </bean>Copy the code
Here you need to use the com. Alibaba. Fescar. Rm. The datasource. DataSourceProxy packaging Druid data source as a direct business data sources, DataSourceProxy is used to intercept and parse business SQL and interact with TCS to coordinate transaction operation state.
-
Configure the Dubbo registry
<dubbo:registry address="nacos://${nacos-server-ip}:8848"/> Copy the code
-
Configuration Fescar GlobalTransactionScanner
<bean class="com.alibaba.fescar.spring.annotation.GlobalTransactionScanner"> <constructor-arg value="dubbo-demo-account-service"/> <constructor-arg value="my_test_tx_group"/> </bean>Copy the code
The first parameter of the constructor is the business-defined applicationId. Ensure that the applicationId is unique if multiple microservices are deployed on a single machine.
The second parameter of the constructor is the Fescar transaction service logical group, which is mapped to the corresponding FesCAR-server cluster name through the configuration center configuration item service.vgroup_mapping.my_test_tx_group. Grouplist is used to obtain the list of available services.
Step 5: Configure the transaction initiator
Configure the following configuration in dubo-business.xml:
- Configure the Dubbo registry as in Step 4
- Configure Fescar GlobalTransactionScanner as in Step 4
-
Add the @GlobalTransactional annotation to the transaction initiator service method
@GlobalTransactional(timeoutMills = 300000, name = "dubbo-demo-tx")Copy the code
TimeoutMills specifies the total timeout duration of the transaction. The default value is 60 seconds. Name specifies the alias of the transaction method signature. The parameters in the annotations can be omitted.
Step 6: Start nacOS-server
- Download the latest nacos-Server release package and unpack it
- Nacos – server operation
Linux/Unix/Mac
sh startup.sh -m standalone
Copy the code
Windows
cmd startup.cmd -m standalone
Copy the code
Visit Nacos console: http://localhost:8848/nacos/index.html#/configurationManagement? dataId=&group=&appName=&namespace
If the access succeeds, the nacos-server service is running successfully (default account/password: Nacos/Nacos).
Step 7: Start the Fescar-server
- Download the latest Release package of Fescar-Server and unzip it
- Initialize the Fescar configuration
Go to the conf folder of the fescar-server decompression directory, confirm the configuration value of nacos-config. TXT, and run the nacos-config.sh script to initialize the configuration.
sh nacos-config.sh $Nacos-Server-IP
Copy the code
eg:
sh nacos-config.sh localhost
Copy the code
After the script is executed, if init nacos config finished, please start fescar-server. Is displayed, the configuration is successfully pushed. For further confirmation, go to the Nacos console configuration list and filter the configuration items for Group=FESCAR_GROUP.
- Example Change the registration mode of the fescar-server service to nacOS
Go to the registry. Conf folder of the fescar-server decompressed directory, change type=”nacos”, and configure nacos properties.
registry {
# file nacos
type = "nacos"
nacos {
serverAddr = "localhost"
namespace = "public"
cluster = "default"
}
file {
name = "file.conf"
}
}Copy the code
ServerAddr: nacos-sever Service address (excluding the port number) nacos.namespace: nacos.serveraddr: nacos-sever service address (excluding the port number) nacos.namespace: Nacos Registration and configuration isolation Namespace nacos.cluster: cluster name of the registration service file.name: type = “file” Configuration file name in the classpath
- Run Fescar – server
Linux/Unix/Mac
Sh $LISTEN_PORT $PATH_FOR_PERSISTENT_DATA $IP(This parameter is optional)Copy the code
Windows
CMD fescar-server.bat $LISTEN_PORT $PATH_FOR_PERSISTENT_DATA $IPCopy the code
L I S T E N P O R T: F E S c a R − S R v E RPATH_FOR_PERSISTENT_DATA: Transaction record file store path (existing path)
$IP(Optional): Specifies the IP address of the FesCAR-server registration service in a multi-IP environment
eg: sh fescar-server.sh 8091 /home/admin/fescar/data/
After successful operation, you can see the service name =serverAddr service registration list on the Nacos console:
Step 8: Start microservices and test them
- Change the service client discovery registration mode to NACOS. For details, see Step 7 [Change the Fescar-Server service registration mode to NacOS]
- Start the DubboAccountServiceStarter
- Start the DubboOrderServiceStarter
- Start the DubboStorageServiceStarter
The three providers that have been started can be seen in the Nacos Console services list:
- Start DubboBusinessTester to test
Note: The transaction is rolled back only when a thrown exception is displayed inside the annotated @GlobalTransactional annotation method. The entire Dubbo service invocation link only needs to be annotated in the service method of the initiator at the beginning of the transaction.
Through the above 8 steps, we achieved data consistency among the three independent micro-services of inventory, order and account in the business of purchasing goods.
Reference links:
Sample address: github.com/fescar-grou…
Fescar: github.com/alibaba/fes…
Dubbo: github.com/apache/incu…
Nacos: github.com/alibaba/nac…
Author: Qing Ming, community nickname Slievrly, one of the sponsors of Fescar open source project, a core r&d member of TXC/GTS of Alibaba Zhongshi, engaged in the core research and development of distributed middleware for a long time, with rich technical accumulation in the field of distributed transactions.
For more information about Fescar:
- Distributed transaction middleware Fescar – RM module source code interpretation
- With regard to Fescar, the open source distributed transaction middleware, we have summarized 13 concerns for developers