面试题答案
一键面试1. Seata核心组件在该场景中的作用
- TC(Transaction Coordinator):事务协调者,维护全局事务的运行状态,负责协调并驱动全局事务的提交或回滚。在电商下单场景中,TC会记录订单创建、库存扣减、支付这一系列操作组成的全局事务的状态。当所有分支事务都成功准备好后,TC会通知各分支事务提交;若有任何一个分支事务失败,TC会通知所有分支事务回滚。
- TM(Transaction Manager):事务管理器,定义全局事务的范围,开始全局事务、提交或回滚全局事务。在用户下单场景中,订单服务扮演TM的角色。订单服务首先开启一个全局事务,在订单创建、库存扣减、支付等操作完成后,根据各操作的结果决定是提交还是回滚全局事务。
- RM(Resource Manager):资源管理器,管理分支事务处理的资源,与TC进行通信,汇报分支事务的状态,并接收TC的指令,执行分支事务的提交或回滚。库存服务和支付服务是RM。库存服务在扣减库存时作为一个分支事务,向TC汇报扣减库存操作的状态,并根据TC的指令决定是否提交或回滚库存扣减操作;支付服务同理,汇报支付操作状态并按指令行事。
2. 配置要点
- 引入依赖:在各个微服务(订单、库存、支付服务)的
pom.xml
中引入Seata相关依赖。例如:
<dependency>
<groupId>io.seata</groupId>
<artifactId>seata-spring-boot-starter</artifactId>
<version>1.4.2</version>
</dependency>
- 配置文件:
- 在每个微服务的
application.yml
中配置Seata相关参数。
seata: application-id: ${spring.application.name} tx-service-group: my_test_tx_group
- 配置Seata Server地址,在
registry.conf
中配置:
registry { type = "nacos" nacos { serverAddr = "127.0.0.1:8848" namespace = "" group = "SEATA_GROUP" application = "seata-server" dataId = "seataServer.properties" username = "nacos" password = "nacos" } } config { type = "nacos" nacos { serverAddr = "127.0.0.1:8848" namespace = "" group = "SEATA_GROUP" dataId = "seataServer.properties" username = "nacos" password = "nacos" } }
- 在Nacos中配置Seata的事务分组与TC的映射关系,在
seataServer.properties
中添加:
service.vgroupMapping.my_test_tx_group=default
- 在每个微服务的
- 数据源代理:在每个微服务中配置数据源代理,将原有的数据源替换为Seata的
DataSourceAutoConfiguration
配置的代理数据源。例如在订单服务的application.yml
中:
spring:
datasource:
driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://localhost:3306/order_db
username: root
password: root
并在SeataAutoConfiguration
类中:
import com.alibaba.druid.pool.DruidDataSource;
import io.seata.spring.boot.autoconfigure.SeataDataSourceAutoConfiguration;
import io.seata.spring.boot.autoconfigure.SeataProperties;
import io.seata.spring.boot.autoconfigure.SeataProperties.DataSource;
import io.seata.spring.boot.autoconfigure.SeataProperties.TxServiceGroup;
import io.seata.spring.boot.autoconfigure.SeataProperties.XaDataSource;
import io.seata.spring.boot.autoconfigure.SeataProperties.XaDataSource.Schema;
import io.seata.spring.boot.autoconfigure.SeataProperties.XaDataSource.Schema.Database;
import io.seata.spring.boot.autoconfigure.SeataProperties.XaDataSource.Schema.Driver;
import io.seata.spring.boot.autoconfigure.SeataProperties.XaDataSource.Schema.JdbcUrl;
import io.seata.spring.boot.autoconfigure.SeataProperties.XaDataSource.Schema.User;
import io.seata.spring.boot.autoconfigure.SeataProperties.XaDataSource.Schema.Password;
import io.seata.spring.boot.autoconfigure.SeataProperties.XaDataSource.Schema.Mode;
import io.seata.spring.boot.autoconfigure.SeataProperties.XaDataSource.Schema.Mode.Xa;
import io.seata.spring.boot.autoconfigure.SeataProperties.XaDataSource.Schema.Mode.At;
import io.seata.spring.boot.autoconfigure.SeataProperties.XaDataSource.Schema.Mode.Tcc;
import io.seata.spring.boot.autoconfigure.SeataProperties.XaDataSource.Schema.Mode.Saga;
import io.seata.spring.boot.autoconfigure.SeataProperties.XaDataSource.Schema.Mode.XaRecovery;
import io.seata.spring.boot.autoconfigure.SeataProperties.XaDataSource.Schema.Mode.AtRecovery;
import io.seata.spring.boot.autoconfigure.SeataProperties.XaDataSource.Schema.Mode.TccRecovery;
import io.seata.spring.boot.autoconfigure.SeataProperties.XaDataSource.Schema.Mode.SagaRecovery;
import io.seata.spring.boot.autoconfigure.SeataProperties.XaDataSource.Schema.Mode.XaBranchRegister;
import io.seata.spring.boot.autoconfigure.SeataProperties.XaDataSource.Schema.Mode.AtBranchRegister;
import io.seata.spring.boot.autoconfigure.SeataProperties.XaDataSource.Schema.Mode.TccBranchRegister;
import io.seata.spring.boot.autoconfigure.SeataProperties.XaDataSource.Schema.Mode.SagaBranchRegister;
import io.seata.spring.boot.autoconfigure.SeataProperties.XaDataSource.Schema.Mode.XaBranchUnregister;
import io.seata.spring.boot.autoconfigure.SeataProperties.XaDataSource.Schema.Mode.AtBranchUnregister;
import io.seata.spring.boot.autoconfigure.SeataProperties.XaDataSource.Schema.Mode.TccBranchUnregister;
import io.seata.spring.boot.autoconfigure.SeataProperties.XaDataSource.Schema.Mode.SagaBranchUnregister;
import io.seata.spring.boot.autoconfigure.SeataProperties.XaDataSource.Schema.Mode.XaBranchCommit;
import io.seata.spring.boot.autoconfigure.SeataProperties.XaDataSource.Schema.Mode.AtBranchCommit;
import io.seata.spring.boot.autoconfigure.SeataProperties.XaDataSource.Schema.Mode.TccBranchCommit;
import io.seata.spring.boot.autoconfigure.SeataProperties.XaDataSource.Schema.Mode.SagaBranchCommit;
import io.seata.spring.boot.autoconfigure.SeataProperties.XaDataSource.Schema.Mode.XaBranchRollback;
import io.seata.spring.boot.autoconfigure.SeataProperties.XaDataSource.Schema.Mode.AtBranchRollback;
import io.seata.spring.boot.autoconfigure.SeataProperties.XaDataSource.Schema.Mode.TccBranchRollback;
import io.seata.spring.boot.autoconfigure.SeataProperties.XaDataSource.Schema.Mode.SagaBranchRollback;
import io.seata.spring.boot.autoconfigure.SeataProperties.XaDataSource.Schema.Mode.XaBranchStatusQuery;
import io.seata.spring.boot.autoconfigure.SeataProperties.XaDataSource.Schema.Mode.AtBranchStatusQuery;
import io.seata.spring.boot.autoconfigure.SeataProperties.XaDataSource.Schema.Mode.TccBranchStatusQuery;
import io.seata.spring.boot.autoconfigure.SeataProperties.XaDataSource.Schema.Mode.SagaBranchStatusQuery;
import io.seata.spring.boot.autoconfigure.SeataProperties.XaDataSource.Schema.Mode.XaBranchLockQuery;
import io.seata.spring.boot.autoconfigure.SeataProperties.XaDataSource.Schema.Mode.AtBranchLockQuery;
import io.seata.spring.boot.autoconfigure.SeataProperties.XaDataSource.Schema.Mode.TccBranchLockQuery;
import io.seata.spring.boot.autoconfigure.SeataProperties.XaDataSource.Schema.Mode.SagaBranchLockQuery;
import io.seata.spring.boot.autoconfigure.SeataProperties.XaDataSource.Schema.Mode.XaBranchRetryCommit;
import io.seata.spring.boot.autoconfigure.SeataProperties.XaDataSource.Schema.Mode.AtBranchRetryCommit;
import io.seata.spring.boot.autoconfigure.SeataProperties.XaDataSource.Schema.Mode.TccBranchRetryCommit;
import io.seata.spring.boot.autoconfigure.SeataProperties.XaDataSource.Schema.Mode.SagaBranchRetryCommit;
import io.seata.spring.boot.autoconfigure.SeataProperties.XaDataSource.Schema.Mode.XaBranchRetryRollback;
import io.seata.spring.boot.autoconfigure.SeataProperties.XaDataSource.Schema.Mode.AtBranchRetryRollback;
import io.seata.spring.boot.autoconfigure.SeataProperties.XaDataSource.Schema.Mode.TccBranchRetryRollback;
import io.seata.spring.boot.autoconfigure.SeataProperties.XaDataSource.Schema.Mode.SagaBranchRetryRollback;
import io.seata.spring.boot.autoconfigure.SeataProperties.XaDataSource.Schema.Mode.XaBranchRetryStatusQuery;
import io.seata.spring.boot.autoconfigure.SeataProperties.XaDataSource.Schema.Mode.AtBranchRetryStatusQuery;
import io.seata.spring.boot.autoconfigure.SeataProperties.XaDataSource.Schema.Mode.TccBranchRetryStatusQuery;
import io.seata.spring.boot.autoconfigure.SeataProperties.XaDataSource.Schema.Mode.SagaBranchRetryStatusQuery;
import io.seata.spring.boot.autoconfigure.SeataProperties.XaDataSource.Schema.Mode.XaBranchRetryLockQuery;
import io.seata.spring.boot.autoconfigure.SeataProperties.XaDataSource.Schema.Mode.AtBranchRetryLockQuery;
import io.seata.spring.boot.autoconfigure.SeataProperties.XaDataSource.Schema.Mode.TccBranchRetryLockQuery;
import io.seata.spring.boot.autoconfigure.SeataProperties.XaDataSource.Schema.Mode.SagaBranchRetryLockQuery;
import io.seata.spring.boot.autoconfigure.SeataProperties.XaDataSource.Schema.Mode.XaBranchAutoCommit;
import io.seata.spring.boot.autoconfigure.SeataProperties.XaDataSource.Schema.Mode.AtBranchAutoCommit;
import io.seata.spring.boot.autoconfigure.SeataProperties.XaDataSource.Schema.Mode.TccBranchAutoCommit;
import io.seata.spring.boot.autoconfigure.SeataProperties.XaDataSource.Schema.Mode.SagaBranchAutoCommit;
import io.seata.spring.boot.autoconfigure.SeataProperties.XaDataSource.Schema.Mode.XaBranchAutoRollback;
import io.seata.spring.boot.autoconfigure.SeataProperties.XaDataSource.Schema.Mode.AtBranchAutoRollback;
import io.seata.spring.boot.autoconfigure.SeataProperties.XaDataSource.Schema.Mode.TccBranchAutoRollback;
import io.seata.spring.boot.autoconfigure.SeataProperties.XaDataSource.Schema.Mode.SagaBranchAutoRollback;
import io.seata.spring.boot.autoconfigure.SeataProperties.XaDataSource.Schema.Mode.XaBranchAutoStatusQuery;
import io.seata.spring.boot.autoconfigure.SeataProperties.XaDataSource.Schema.Mode.AtBranchAutoStatusQuery;
import io.seata.spring.boot.autoconfigure.SeataProperties.XaDataSource.Schema.Mode.TccBranchAutoStatusQuery;
import io.seata.spring.boot.autoconfigure.SeataProperties.XaDataSource.Schema.Mode.SagaBranchAutoStatusQuery;
import io.seata.spring.boot.autoconfigure.SeataProperties.XaDataSource.Schema.Mode.XaBranchAutoLockQuery;
import io.seata.spring.boot.autoconfigure.SeataProperties.XaDataSource.Schema.Mode.AtBranchAutoLockQuery;
import io.seata.spring.boot.autoconfigure.SeataProperties.XaDataSource.Schema.Mode.TccBranchAutoLockQuery;
import io.seata.spring.boot.autoconfigure.SeataProperties.XaDataSource.Schema.Mode.SagaBranchAutoLockQuery;
import io.seata.spring.boot.autoconfigure.SeataProperties.XaDataSource.Schema.Mode.XaBranchAutoRetryCommit;
import io.seata.spring.boot.autoconfigure.SeataProperties.XaDataSource.Schema.Mode.AtBranchAutoRetryCommit;
import io.seata.spring.boot.autoconfigure.SeataProperties.XaDataSource.Schema.Mode.TccBranchAutoRetryCommit;
import io.seata.spring.boot.autoconfigure.SeataProperties.XaDataSource.Schema.Mode.SagaBranchAutoRetryCommit;
import io.seata.spring.boot.autoconfigure.SeataProperties.XaDataSource.Schema.Mode.XaBranchAutoRetryRollback;
import io.seata.spring.boot.autoconfigure.SeataProperties.XaDataSource.Schema.Mode.AtBranchAutoRetryRollback;
import io.seata.spring.boot.autoconfigure.SeataProperties.XaDataSource.Schema.Mode.TccBranchAutoRetryRollback;
import io.seata.spring.boot.autoconfigure.SeataProperties.XaDataSource.Schema.Mode.SagaBranchAutoRetryRollback;
import io.seata.spring.boot.autoconfigure.SeataProperties.XaDataSource.Schema.Mode.XaBranchAutoRetryStatusQuery;
import io.seata.spring.boot.autoconfigure.SeataProperties.XaDataSource.Schema.Mode.AtBranchAutoRetryStatusQuery;
import io.seata.spring.boot.autoconfigure.SeataProperties.XaDataSource.Schema.Mode.TccBranchAutoRetryStatusQuery;
import io.seata.spring.boot.autoconfigure.SeataProperties.XaDataSource.Schema.Mode.SagaBranchAutoRetryStatusQuery;
import io.seata.spring.boot.autoconfigure.SeataProperties.XaDataSource.Schema.Mode.XaBranchAutoRetryLockQuery;
import io.seata.spring.boot.autoconfigure.SeataProperties.XaDataSource.Schema.Mode.AtBranchAutoRetryLockQuery;
import io.seata.spring.boot.autoconfigure.SeataProperties.XaDataSource.Schema.Mode.TccBranchAutoRetryLockQuery;
import io.seata.spring.boot.autoconfigure.SeataProperties.XaDataSource.Schema.Mode.SagaBranchAutoRetryLockQuery;
import io.seata.spring.boot.autoconfigure.SeataProperties.XaDataSource.Schema.Mode.XaBranchAutoCommitOnSuccess;
import io.seata.spring.boot.autoconfigure.SeataProperties.XaDataSource.Schema.Mode.AtBranchAutoCommitOnSuccess;
import io.seata.spring.boot.autoconfigure.SeataProperties.XaDataSource.Schema.Mode.TccBranchAutoCommitOnSuccess;
import io.seata.spring.boot.autoconfigure.SeataProperties.XaDataSource.Schema.Mode.SagaBranchAutoCommitOnSuccess;
import io.seata.spring.boot.autoconfigure.SeataProperties.XaDataSource.Schema.Mode.XaBranchAutoRollbackOnFailure;
import io.seata.spring.boot.autoconfigure.SeataProperties.XaDataSource.Schema.Mode.AtBranchAutoRollbackOnFailure;
import io.seata.spring.boot.autoconfigure.SeataProperties.XaDataSource.Schema.Mode.TccBranchAutoRollbackOnFailure;
import io.seata.spring.boot.autoconfigure.SeataProperties.XaDataSource.Schema.Mode.SagaBranchAutoRollbackOnFailure;
import io.seata.spring.boot.autoconfigure.SeataProperties.XaDataSource.Schema.Mode.XaBranchAutoStatusQueryOnSuccess;
import io.seata.spring.boot.autoconfigure.SeataProperties.XaDataSource.Schema.Mode.AtBranchAutoStatusQueryOnSuccess;
import io.seata.spring.boot.autoconfigure.SeataProperties.XaDataSource.Schema.Mode.TccBranchAutoStatusQueryOnSuccess;
import io.seata.spring.boot.autoconfigure.SeataProperties.XaDataSource.Schema.Mode.SagaBranchAutoStatusQueryOnSuccess;
import io.seata.spring.boot.autoconfigure.SeataProperties.XaDataSource.Schema.Mode.XaBranchAutoLockQueryOnSuccess;
import io.seata.spring.boot.autoconfigure.SeataProperties.XaDataSource.Schema.Mode.AtBranchAutoLockQueryOnSuccess;
import io.seata.spring.boot.autoconfigure.SeataProperties.XaDataSource.Schema.Mode.TccBranchAutoLockQueryOnSuccess;
import io.seata.spring.boot.autoconfigure.SeataProperties.XaDataSource.Schema.Mode.SagaBranchAutoLockQueryOnSuccess;
import io.seata.spring.boot.autoconfigure.SeataProperties.XaDataSource.Schema.Mode.XaBranchAutoRetryCommitOnSuccess;
import io.seata.spring.boot.autoconfigure.SeataProperties.XaDataSource.Schema.Mode.AtBranchAutoRetryCommitOnSuccess;
import io.seata.spring.boot.autoconfigure.SeataProperties.XaDataSource.Schema.Mode.TccBranchAutoRetryCommitOnSuccess;
import io.seata.spring.boot.autoconfigure.SeataProperties.XaDataSource.Schema.Mode.SagaBranchAutoRetryCommitOnSuccess;
import io.seata.spring.boot.autoconfigure.SeataProperties.XaDataSource.Schema.Mode.XaBranchAutoRetryRollbackOnFailure;
import io.seata.spring.boot.autoconfigure.SeataProperties.XaDataSource.Schema.Mode.AtBranchAutoRetryRollbackOnFailure;
import io.seata.spring.boot.autoconfigure.SeataProperties.XaDataSource.Schema.Mode.TccBranchAutoRetryRollbackOnFailure;
import io.seata.spring.boot.autoconfigure.SeataProperties.XaDataSource.Schema.Mode.SagaBranchAutoRetryRollbackOnFailure;
import io.seata.spring.boot.autoconfigure.SeataProperties.XaDataSource.Schema.Mode.XaBranchAutoRetryStatusQueryOnSuccess;
import io.seata.spring.boot.autoconfigure.SeataProperties.XaDataSource.Schema.Mode.AtBranchAutoRetryStatusQueryOnSuccess;
import io.seata.spring.boot.autoconfigure.SeataProperties.XaDataSource.Schema.Mode.TccBranchAutoRetryStatusQueryOnSuccess;
import io.seata.spring.boot.autoconfigure.SeataProperties.XaDataSource.Schema.Mode.SagaBranchAutoRetryStatusQueryOnSuccess;
import io.seata.spring.boot.autoconfigure.SeataProperties.XaDataSource.Schema.Mode.XaBranchAutoRetryLockQueryOnSuccess;
import io.seata.spring.boot.autoconfigure.SeataProperties.XaDataSource.Schema.Mode.AtBranchAutoRetryLockQueryOnSuccess;
import io.seata.spring.boot.autoconfigure.SeataProperties.XaDataSource.Schema.Mode.TccBranchAutoRetryLockQueryOnSuccess;
import io.seata.spring.boot.autoconfigure.SeataProperties.XaDataSource.Schema.Mode.SagaBranchAutoRetryLockQueryOnSuccess;
import javax.sql.DataSource;
import org.springframework.boot.autoconfigure.jdbc.DataSourceProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
@Configuration
public class SeataAutoConfiguration {
@Bean
@Primary
public DataSource dataSource(DataSourceProperties properties) {
DruidDataSource druidDataSource = properties.initializeDataSourceBuilder().type(DruidDataSource.class).build();
return new io.seata.spring.boot.autoconfigure.SeataDataSourceAutoConfiguration.SeataAutoDataSource(druidDataSource);
}
}
3. 代码实现要点
- 订单服务(TM):
import io.seata.spring.annotation.GlobalTransactional; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; @Service public class OrderService { @Autowired private InventoryService inventoryService; @Autowired private PaymentService paymentService; @GlobalTransactional(name = "order-create-tx", rollbackFor = Exception.class) @Transactional public void createOrder(Order order) { // 创建订单 create(order); // 调用库存服务扣减库存 inventoryService.decrease(order.getProductId(), order.getQuantity()); // 调用支付服务进行支付 paymentService.pay(order.getUserId(), order.getTotalAmount()); } private void create(Order order) { // 订单创建逻辑,向数据库插入订单数据 } }
- 库存服务(RM):
import io.seata.spring.annotation.GlobalLock; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; @Service public class InventoryService { @GlobalLock @Transactional public void decrease(Long productId, Integer quantity) { // 扣减库存逻辑,更新数据库库存数据 } }
- 支付服务(RM):
import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; @Service public class PaymentService { @Transactional public void pay(Long userId, BigDecimal amount) { // 支付逻辑,更新数据库支付记录等 } }
通过以上Seata框架的设计、配置与代码实现,即可在Spring Cloud Alibaba微服务架构电商场景中实现分布式事务,保证订单创建、库存扣减和支付操作的一致性。