分布式事务是指在分布式环境下,对多个数据资源进行并行操作时,需要保持数据资源之间的一致性和完整性,同时具有ACID的特性。在分布式系统中,由于存在多个数据存储节点、网络延迟、可用性等问题,导致分布式事务的实现相比较于单节点事务要更加复杂和困难。
两阶段提交(Two-Phase Commit, 2PC):事务协调者(TC)首先向所有参与者(P)发出“预提交”(prepare)请求,各参与者对消息进行确认操作。如果所有参与者都能正常执行,则协调者向参与者发出“正式提交”请求,各参与者将事务提交到本地数据库,返回确认消息。如果该过程中出现任何一个参与者无法提交,则会进行回滚操作,使得全局事务回滚到最初的状态。
补偿事务(TCC):TCC事务将一个事务以尽可能简单的形式分解为三个步骤——试着去执行它,检查是否可以提交,如果不能提交,则回滚已经执行的动作。在TCC事务中,需要实现try、confirm和cancel三个接口,通过调用confirm、cancel接口实现提交和回滚操作。
Saga事务:Saga是一种支持可撤销和部署在多个实例之间的长事务处理模式。Saga事务将长事务拆分为多个小事务,每个小事务之间不再强制保证强一致性,而是通过异步消息通信的方式进行顺序化处理,从而降低了系统的复杂度和开发成本。
消息队列事务:在消息中间件的支持下,将消息的生产者和消费者进行事务性合作。
以上解决方案都有其适用场景和实现细节,需要根据具体的业务需求进行选择。同时,在应用分布式事务时还需要考虑到数据一致性、可靠性、性能、可扩展性等方面的问题。
两阶段提交(Two-Phase Commit,2PC)是实现分布式事务的一种较为传统的方式,它通过引入一个协调者(Coordinator)来协调多个参与者(Participant)的提交行为,从而保证分布式事务的原子性和一致性。
2PC的过程如下所示:
阶段一:
协调者向所有分布式事务参与者发送“canCommit”请求。
各参与者接收到请求后,会相应的执行数据准备工作。如果参与者在执行准备工作时发现有不可处理的错误,则向协调者发送“NO”响应。
如果所有参与者都成功的执行了准备工作,则向协调者发送“YES”响应。
阶段二:
如果协调者在阶段一收到了所有参与者的“YES”响应,则向所有参与者发送“doCommit”请求。参与者收到请求后执行事务提交,并向协调者返回“ACK”表示提交成功。
如果协调者在阶段一或二的任一阶段收到了任何一个参与者的“NO”响应或超时,则向所有参与者发送“doAbort”请求,参与者执行事务回滚操作,并向协调者返回“ACK”表示回滚成功。
2PC的具体实现有以下几点需要注意:
总之,2PC虽然具有原子性和一致性的特点,但其实现复杂度较高,同时存在一些可能导致性能下降和可用性降低的问题,因此需要根据具体的业务场景进行权衡和选择。
以转账业务为例子,介绍使用两阶段提交(2PC)实现分布式事务的过程。
假设有两个账户A和B,我们需要在分布式环境下实现从账户A向账户B转账的业务。具体过程如下:
例如,账户A和B的Participator成功处理账户余额变动操作,向Coordinator发送了“YES”响应。协调者收到两个参与者的“YES”响应后,决定提交事务。协调者向账户A和B的Participator发送“doCommit”请求,各参与者收到请求后执行事务提交操作,返回“ACK”表示提交成功。
如果账户A的余额不足,导致账户A的Participator向协调者发送了“NO”响应,则协调者向所有参与者发送“doAbort”请求,各参与者执行事务回滚操作,并返回“ACK”表示回滚成功。
以上就是使用两阶段提交(2PC)实现分布式事务的过程,可以保证分布式环境下数据的一致性和完整性。
TCC(Try-Confirm-Cancel)是一种实现分布式事务的较为流行的方式,它将一个分布式事务拆解成“尝试”(Try)、“确认”(Confirm)和“撤销”(Cancel)三个阶段,从而保证了事务的原子性和一致性。
具体来说,TCC实现分布式事务的过程如下:
TCC的实现需要从以下几个方面进行考虑:
总之,TCC是实现分布式事务的较为常用的方式之一,相对于2PC而言,它的性能和可靠性都更加优秀,实现的复杂度相对2PC要低。
假设我们有一个转账业务,需要在分布式环境下完成,使用TCC实现分布式事务的过程如下:
例如,A账户向B账户转移1000元,使用TCC实现分布式事务的过程如下:
以上就是使用TCC实现分布式事务的具体过程了。TCC通过将分布式事务拆分成“尝试”、“确认”和“撤销”三个阶段,以最小的开销保障了分布式事务的可靠性和一致性。
Saga是一种基于补偿机制的分布式事务解决方案。它通过将整个事务拆解成一系列的局部事务,每个局部事务负责更新自己的本地状态,并通过发送compensating action来完成事务的撤销操作。Saga的核心思想是以“最小承诺”减少分布式事务的范围,从而消除了分布式事务的复杂性,更加适用于微服务架构中的分布式场景。
使用Saga实现分布式事务的过程如下:
例如,下面是一个Saga事务的示例:
在这个示例中,如果任何一个局部事务出现失败,Saga事务的协调器将调用compensating action来撤销操作,以保证整个事务的一致性和可靠性。
总之,Saga是一种基于补偿机制的分布式事务解决方案,它提供了一种减少事务范围的方案,从而消除分布式事务中的复杂性,更适合于微服务架构中的分布式场景。使用Saga时需要定义Saga事务、执行Saga事务、Saga事务状态管理和保障高可用性。
分布式事务中的消息事务,通常指的是在事务执行过程中所使用的消息队列的事务。实现消息事务的方式主要有两种,分别是本地消息事务和分布式消息事务。
1、本地消息事务:
本地消息事务是在消息发送方和接收方所在的数据库事务中,通过消息队列来实现数据的异步操作。在本地消息事务中,发送方发送消息时,将消息插入到一个本地消息表中,并在当前数据库事务中进行提交。如果后续在事务执行过程中需要回滚,也需要将已经发送的消息删除。接收方在收到消息后,需要在本地数据库事务中进行处理。
2、分布式消息事务:
分布式消息事务需要消息队列支持分布式事务的功能。常见的有基于消息队列内嵌事务的分布式消息事务和基于两阶段提交的分布式消息事务。其中基于消息队列内嵌事务的方式,比如 Kafka 中的事务支持,通过消息队列内嵌事务来实现分布式事务的功能。在使用该方式时,消息的发送方和接收方都需要在同一个事务中进行,如果事务出现问题,则消息会被回滚。
基于两阶段提交的分布式消息事务,则将消息队列作为一个参与者,与数据库事务一起参与分布式事务的处理。在该模式下,在分布式事务提交之前需要进行两个阶段的协作:第一阶段中,记录消息的相关信息并将消息发送到消息队列;第二阶段中,消息队列接收事务协调器发送的消息,确认消息可以发送,并等待最终的确认信息。如果分布式事务提交成功,则消息队列会将消息发送出去;如果分布式事务回滚,则消息队列不会发送消息。
总的来说,实现分布式事务的消息事务需要考虑到消息的发送、接收以及在分布式事务中的协作等方面,采用合适的技术和方案来实现。
在实现分布式事务时,可以采用本地事务表的形式来实现。具体实现方式如下:
Spring Boot 集成 Seata 可以使用 Seata 官方提供的 Spring Boot Starter,具体使用方法可参考 Seata 的官方文档。
使用消息队列(MQ)实现分布式事务,通常是采用异步确保的方式。具体方式如下:
需要注意的是,使用消息队列实现分布式事务时,由于涉及到异步操作,因此需要保证消息的可靠性,比如消息持久化、重试机制等。同时,也需要考虑到可能出现消息重复消费的情况,需要在消息队列中进行判重等操作。
具体实现时,可以使用消息中间件(比如 RabbitMQ、Kafka)来实现分布式事务的消息队列。此外,在使用分布式事务时,也可以考虑分布式事务框架,比如 Seata、Hmily 等,它们可以支持分布式事务的协调、管理,提供更便捷的分布式事务实现方式。
Seata是一种开源的分布式事务解决方案,它提供高效的多数据源、跨服务端的分布式事务管理能力。Seata将每个事务定义为一个全局唯一的XID(X/Open XA标准中的标识符),通过将每个参与方的local transaction纳入全局事务的管理体系中,实现分布式事务的可靠性,保证多个事务操作的原子性、一致性和隔离性。
使用Seata实现分布式事务的过程如下:
例如,下面是使用Seata实现转账业务的示例:
以上就是使用Seata实现分布式事务的过程,通过Seata对局部事务的承诺和向Seata Server的注册管理,以达到全局事务的控制和管理,实现了分布式事务的可靠性和一致性。
Seata支持三种分布式事务模式,分别是AT、TCC和SAGA,每种模式都有其适用场景,可以根据实际需求选择使用。
1、AT模式
AT(Alter Table)模式利用数据库提供的ACID事务机制,能够减少代码的修改量,最大限度地利用已有的资源,并提供高性能和简便管理。在AT模式下,Seata代理会拦截每一个涉及到数据库的SQL操作,当分支事务进行提交时,Seata会自动将所有修改的数据都写入redo log,并在回滚时将这些操作删除。AT模式适用于业务逻辑简单,对实时性有要求的场景。
2、TCC模式
TCC(Try Confirm Cancel)模式是一种基于业务逻辑实现的分布式事务模式。TCC模式的原理是将一个完整交易拆分成三个阶段——预留资源(try)、执行操作(confirm)和取消操作(cancel),每个阶段对应一个事务操作,通过自定义的业务逻辑实现事务的管理。在TCC模式下,Seata代理会拦截业务请求,同时根据业务逻辑调用try、confirm、cancel的方法。TCC模式适用于业务逻辑复杂,需要定制化事务管理和数据处理的场景。
3、SAGA模式
SAGA(Saga pattern)模式是一种基于补偿机制的分布式事务模式。相比于AT和TCC模式,SAGA模式更加适用于系统与系统之间的分布式事务场景。SAGA模式将复杂的分布式事务拆分成一个个小的本地事务和补偿操作,并通过补偿操作保证整个事务的一致性。在SAGA模式下,Seata会根据应用程序的Saga定义动态地创建和管理micro transactions,从而实现不同服务之间的交互和事务的处理。SAGA模式适用于不同服务之间存在多阶段业务流程,需要根据业务逻辑实现事务管理的场景。
总之,Seata支持三种分布式事务模式,每种模式都适合不同的应用场景和业务需求。在应用中选择合适的事务模式非常重要,可以根据具体业务需求选择AT、TCC和SAGA中的一种或几种来实现分布式事务。
在Spring Boot中使用Seata的AT模式,大概需要以下步骤:
io.seata
seata-spring-boot-starter
1.4.2
在 application.yml 或 application.properties 中添加以下Seata配置项:
spring:
application:
name: xxx-service # 这里是你的服务名,需要与Seata Server上的注册信息对应
cloud:
alibaba:
seata:
tx-service-group: my_test_tx_group # 这里指定Seata服务的事务组名
service:
vgroup:
my_test_tx_group: "default" # 这里指定Seata Server默认的事务组名
group:
my_test_tx_group: # 把这个服务注册到Seata Server的事务组名
default:
annotation-interceptor-order: 1
undo-data-validation: true
mode: AT # 这里指定AT模式
log-store: db
lock:
type: DB
# 记得把下面的DB配置改成你的数据库配置
db:
datasource: druid # javax.sql.DataSource类型,建议使用集成连接池,例如druid、hikari等
...
report-retry-count: 5
在 Seata Server 的 registry.conf
和 file.conf
文件中,需要加入对本服务的配置:
[registry]
# example: file:/registry
type: file
nacos:
serverAddr: localhost:8848
namespace: please_set_your_namespace
cluster: default
client:
...
customizedRegistryClassName: io.seata.registry.FileRegistry
applicationId: my_test_tx_group
txServiceGroup: my_test_tx_group
env: test
# file registry config
file:
name: file.conf
[registry-file]
type: file
serverList: file://registry
[service]
vgroupMapping.my_test_tx_group=default
default.grouplist=file://127.0.0.1:8091
enableDegrade=false
disableGlobalTransaction=false
在需要使用Seata的分布式事务的方法上加上@GlobalTransactional注解,则此方法即变成了全局事务,如下所示:
@Service
public class OrderServiceImpl implements OrderService {
@Autowired
OrderDAO orderDAO;
@GlobalTransactional(name = "create-order", rollbackFor = Exception.class)
@Override
public Integer createOrder(OrderDTO orderDTO) {
// 业务逻辑
}
}
其中,@GlobalTransactional注解的name属性标注此次全局事务的名称,rollbackFor属性标注回滚的异常类型。
最后,配置好之后运行服务,如果一切正常,你就可以在 Seata Server 的事务列表中看到你的服务加入了一个新的分布式事务了。
通过以上步骤,我们就可以在Spring Boot应用中使用Seata的AT模式实现分布式事务管理。
在Spring Boot中使用Seata的TCC模式,大概需要以下步骤:
io.seata
seata-spring-boot-starter
1.4.2
在 application.yml 或 application.properties 中添加以下Seata配置项:
spring:
application:
name: xxx-service # 这里是你的服务名,需要与Seata Server上的注册信息对应
cloud:
alibaba:
seata:
tx-service-group: my_test_tx_group # 这里指定Seata服务的事务组名
service:
vgroup:
my_test_tx_group: "default" # 这里指定Seata Server默认的事务组名
group:
my_test_tx_group: # 把这个服务注册到Seata Server的事务组名
default:
annotation-interceptor-order: 1
undo-data-validation: true
mode: TCC # 这里指定TCC模式
log-store: none
lock:
type: db # TCC模式锁的类型需要设为db
db:
...
report-retry-count: 5
在 Seata Server 的 registry.conf
和 file.conf
文件中,需要加入对本服务的配置:
[registry]
# example: file:/registry
type: file
nacos:
serverAddr: localhost:8848
namespace: please_set_your_namespace
cluster: default
client:
...
customizedRegistryClassName: io.seata.registry.FileRegistry
applicationId: my_test_tx_group
txServiceGroup: my_test_tx_group
env: test
# file registry config
file:
name: file.conf
[registry-file]
type: file
serverList: file://registry
[service]
vgroupMapping.my_test_tx_group=default
default.grouplist=file://127.0.0.1:8091
enableDegrade=false
disableGlobalTransaction=false
在需要使用Seata的分布式事务的方法上加上@TccTransaction注解,接着实现该方法对应的三个方法(try、confirm、cancel),同时这三个方法需要使用@Compensable注解,如下所示:
@Service
public class OrderServiceImpl implements OrderService {
@Autowired
OrderDAO orderDAO;
@TccTransaction(confirmMethod = "confirmCreateOrder", cancelMethod = "cancelCreateOrder")
@Override
public boolean createOrder(OrderDTO orderDTO) {
// TCC try方法,不需要做什么
return true;
}
@Compensable(confirmMethod = "confirmCreateOrder", cancelMethod = "cancelCreateOrder")
public void tryCreateOrder(OrderDTO orderDTO) {
// TCC try方法,预留资源
orderDAO.insert(orderDTO);
}
@Compensable(confirmMethod = "confirmCreateOrder", cancelMethod = "cancelCreateOrder")
public void confirmCreateOrder(OrderDTO orderDTO) {
// TCC confirm方法,提交分布式事务
}
@Compensable(confirmMethod = "confirmCreateOrder", cancelMethod = "cancelCreateOrder")
public void cancelCreateOrder(OrderDTO orderDTO) {
// TCC cancel方法,回滚分布式事务
orderDAO.delete(orderDTO.getId());
}
}
其中,@TccTransaction注解在方法级别上标明当前方法需要支持分布式事务,同时指定了try方法对应的confirm方法和cancel方法。
而@Compensable注解则在子方法级别上标注了当前方法需要纳入分布式事务的管理,同时指定了该方法在confirm和cancel时需要执行的方法。
最后,配置好之后运行服务,如果一切正常,你就可以在 Seata Server 的事务列表中看到你的服务加入了一个新的分布式事务了。
通过以上步骤,我们就可以在Spring Boot应用中使用Seata的TCC模式实现分布式事务管理。
在 Spring Boot 中使用 Seata 的 Saga 模式,需要以下步骤:
1、引入相关依赖
io.seata
seata-spring-boot-starter
1.4.2
2、配置文件修改
在 application.yml 或 application.properties 中添加以下 Seata 配置项:
# Seata 配置
spring:
application:
name: xxx-service # 这里是你的服务名,需要与 Seata Server 上的注册信息对应
cloud:
alibaba:
seata:
tx-service-group: my_test_tx_group # 这里指定 Seata 服务的事务组名,需要与 Seata Server 上的设置一致
service:
vgroup:
my_test_tx_group: "default" # 这里指定 Seata Server 默认的事务组名
group:
my_test_tx_group: # 把这个服务注册到 Seata Server 上的事务组名
default:
mode: SAGA # 指定 saga 模式
health-check: false
report-retry-count: 5
max-commit-retry-timeout: 300
max-rollback-retry-timeout: 30
3、配置 Seata Server 的 endpoint
在 Seata Server 的配置文件 registry.conf
中,需要为每个要加入 Saga 模式的服务,配置其 endpoint。这里以两个服务为例:
[registry]
# example: file:/registry
type: file
nacos:
serverAddr: localhost:8848
namespace: please_set_your_namespace
cluster: default
client:
...
customizedRegistryClassName: io.seata.registry.FileRegistry
applicationId: my_test_tx_group
txServiceGroup: my_test_tx_group
env: test
# file registry config
file:
name: file.conf
[registry-file]
type: file
serverList: file://registry
[service]
vgroupMapping.my_test_tx_group=default
default.grouplist=file://127.0.0.1:8091,file://127.0.0.1:8092
enableDegrade=false
disableGlobalTransaction=false
[saga]
store.mode=db # saga 模式需要指定 store.mode 为 db
store.db.driver-class-name=com.mysql.cj.jdbc.Driver # 使用 MySQL 数据库存储 Saga 状态
store.db.url=jdbc:mysql://localhost:3306/seata_saga?useUnicode=true&characterEncoding=UTF-8&autoReconnect=true&useSSL=false
store.db.username=root
store.db.password=123456
store.db.min-conn=5
store.db.max-conn=30
store.db.global-table-name=seata_global_table # 全局事务表名,默认值为global_table
store.db.branch-table-name=seata_branch_table # 分支事务表名,默认值为branch_table
store.file.path=/seata/saga # 使用文件存储 Saga 状态
其中,store.mode
需要指定为 db
,store.db
指定数据库相关信息。
4、编写 Saga 并添加 @SagaTransactional 注解
在需要实现 Saga 模式的业务操作方法上添加 @SagaTransactional
注解,并编写与之对应的 Saga 对象及其步骤执行逻辑。
下面是一个示例:
@Service
public class OrderServiceImpl implements OrderService {
@Autowired
private OrderDAO orderDAO;
/**
* 创建订单
*/
@SagaTransactional
@Override
public void createOrder(OrderDTO orderDTO) {
// 扣减商品库存
ProductReduceStockDTO productReduceStockDTO = new ProductReduceStockDTO(orderDTO.getProductId(), orderDTO.getAmount());
productClient.reduceStock(productReduceStockDTO);
// 下单
orderDAO.insert(orderDTO);
// 发送支付事务
SagaRequest sagaRequest = new SagaRequest();
sagaRequest.setServiceName("account-service");
sagaRequest.setMethodName("pay");
sagaRequest.setPayloads(new Object[]{orderDTO.getUserId(), orderDTO.getTotalAmount()});
SagaDefinition sagaDefinition = new SagaDefinition<>();
sagaDefinition.setSagaName("create-order-saga");
sagaDefinition.setPayload(orderDTO);
sagaDefinition.setSteps(Arrays.asList(
new SagaStep<>("product-service", "reduceStock", productReduceStockDTO),
new SagaStep<>("order-service", "insert", orderDTO),
new SagaStep<>(sagaRequest)
));
SagaContext start = SagaContext.start();
SagaManager.executeSaga(sagaDefinition, start);
}
@CompensableConfirm
public void createOrderConfirm(OrderDTO orderDTO) {
// do nothing
}
@CompensableCancel
public void createOrderCancel(OrderDTO orderDTO) {
orderDAO.delete(orderDTO.getId());
}
}
其中,@SagaTransactional
注解在方法上表示这是一个 Saga 分布式事务操作。
SagaDefinition
表示一个 Saga 分布式事务的定义,包含了该 Saga 的名称、开始时的 payload(启动该 Saga 执行的参数)、以及一系列的步骤,每个步骤都是一个 SagaStep
对象。
@CompensableConfirm
和 @CompensableCancel
注解分别表示执行确认和取消操作。这些方法的实现应当和原始操作相反,以确保分布式事务的完整性。
5、运行服务
配置好 Seata Server 和相关配置信息之后,就可以启动应用并运行测试了。如果一切正常,你就可以在 Seata Server 的 Saga 实例中看到对应的实例,并可以查看各个步骤的执行结果。
通过以上步骤,我们就可以在 Spring Boot 应用中使用 Seata 的 Saga 模式实现分布式事务管理。
在实现分布式事务时,需要注意以下几个方面:
以下是一些关于分布式事务的常见面试考点:
分布式事务是指跨越多个计算机或者系统的一种事务,并且在多个数据库、文件系统或其他系统资源上跨越多个事务管理器或协调器。分布式事务需要保证数据在分布式环境下的一致性。
分布式事务的实现方式有以下几种方式:
2PC (Two-Phase Commit) 是一种分布式事务的实现方式。在 2PC 中,协调者将会在两个阶段来提交事务:prepare 和 commit。在 prepare 阶段,协调者会向所有参与者通知分布式事务的准备状态,并要求各个参与者在本地准备好事务。在 commit 阶段,如果所有参与者在 prepare 阶段都反馈了已准备好事务的状态,协调者会通知所有参与者提交事务,否则协调者会请求所有参与者回滚事务。
2PC 的优点是:
2PC 的缺点是:
可靠消息最终一致性框架的实现方式有以下几种方式:
本文由 mdnice 多平台发布