文章目录
七、回滚机制——事务回滚
1. 事务回滚
1.1 单库事务回滚:
1.2 分布式事务回滚
2. 事务回滚实现案例
2.1 单库事务回滚
2.2 分布式事务回滚
2.2.1 两阶段提交协议(2PC)
2.2.2 三阶段提交(3PC)
2.2.3 TCC 模式(Try-Confirm/Cancel)
2.2.4 Sagas 模式
总结
3. 实际应用场景
七、回滚机制——事务回滚
回滚是指在程序或数据出现错误时,将其恢复到最近的一个正确版本的行为。常见的回滚机制包括事务回滚、代码库回滚、部署版本回滚、数据版本回滚、静态资源版本回滚等。有效的回滚机制可以确保系统在出现问题时能够维持高可用性和数据一致性。
1. 事务回滚
事务回滚是指在执行数据库操作时,如果遇到问题,需要将事务中已执行的操作全部撤销,以防止数据不一致。在处理单库事务时,可以直接使用相关 SQL 语句进行回滚。而在分布式数据库环境中,需要采取更加复杂的事务回滚机制,如分布式事务管理协议。
以下是一些常见的事务回滚策略:
1.1 单库事务回滚:
实施方式:使用数据库的事务管理功能进行回滚。如果某个 SQL 执行失败,可以使用 ROLLBACK 命令撤销之前的所有操作。
示例:
BEGIN;
-- 执行多个 SQL 操作
-- 如果其中一个操作失败
ROLLBACK; -- 撤销所有操作
COMMIT; -- 提交事务
1.2 分布式事务回滚
分布式事务回滚 是指在分布式系统中,当多个数据库或服务参与一个事务时,如何处理事务中的失败和回滚问题。由于涉及多个系统或数据库,确保事务的一致性和完整性变得更加复杂。常见的分布式事务协议包括两阶段提交(2PC)、三阶段提交(3PC)、TCC 模式和 Sagas 模式。
以下是这些协议的详细介绍:
两阶段提交协议(2PC)
原理: 两阶段提交协议(Two-Phase Commit, 2PC)是一种经典的分布式事务协议,用于确保多个参与者在分布式事务中的一致性。协议分为两个阶段:
准备阶段:协调者向所有参与者询问是否可以提交事务。参与者准备事务并返回响应。
提交阶段:协调者根据所有参与者的响应决定是否提交事务。如果所有参与者都同意提交,协调者发出提交指令;否则,协调者发出回滚指令。
示例: 在一个电商系统中,进行订单结算时,涉及多个服务如库存服务、支付服务和订单服务。协调者首先询问这些服务是否准备好提交订单,所有服务同意后,协调者发出提交指令,否则发出回滚指令。
三阶段提交协议(3PC)
原理: 三阶段提交协议(Three-Phase Commit, 3PC)是在两阶段提交的基础上增加了一个中间阶段,以提高容错能力。协议的三个阶段包括:
准备阶段:协调者询问所有参与者是否可以提交事务。
预提交阶段:参与者执行事务的预提交操作,准备好提交。
提交阶段:协调者发出最终的提交指令,参与者完成事务提交。
示例: 在分布式银行系统中,进行跨银行转账时,协调者首先询问各银行是否准备好进行转账,然后各银行执行预提交操作(如冻结资金),最后协调者发出最终的提交指令。如果某一阶段出现问题,系统可以采取适当措施进行处理。
TCC 模式(Try-Confirm/Cancel)
原理: TCC 模式(Try-Confirm/Cancel)将事务分为三个阶段:Try(预占资源)、Confirm(确认资源)和 Cancel(取消资源)。每个阶段分别处理资源的预占、确认或取消,以保证事务的最终一致性。
Try:尝试预占资源,如扣减库存,但不立即提交。
Confirm:如果所有 Try 操作成功,执行确认操作,如正式扣除库存。
Cancel:如果 Try 操作失败,执行取消操作,如恢复库存。
示例: 在电商系统中,用户下单时先预占库存(Try),如果用户支付成功则确认库存(Confirm),如果支付失败则取消库存操作(Cancel)。这样可以保证库存的最终一致性。
Sagas 模式
原理: Sagas 模式将一个大事务拆分为多个子事务,每个子事务都有对应的补偿操作。每个子事务在执行失败时,可以通过补偿操作回滚之前成功的子事务,以保证事务的最终一致性。
示例: 在电商系统中,下单、库存扣减、优惠券发放等操作可以作为独立的子事务处理。每个子事务在失败时会触发对应的补偿操作,如恢复库存、退还优惠券等,确保整个事务的一致性。
2. 事务回滚实现案例
2.1 单库事务回滚
在 Spring Boot 中,单库事务管理由 @Transactional 注解提供。可以在服务层使用此注解来管理事务的开始、提交和回滚。
示例:
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
@Service
public class OrderService {
@Autowired
private OrderRepository orderRepository;
@Autowired
private InventoryRepository inventoryRepository;
@Transactional
public void placeOrder(Order order) {
orderRepository.save(order);
// 扣减库存
if (inventoryRepository.decrementStock(order.getItemId(), order.getQuantity()) == 0) {
throw new RuntimeException("库存不足");
}
}
}
说明:
@Transactional 注解确保方法执行过程中,如果发生异常,则所有操作都会回滚。
2.2 分布式事务回滚
2.2.1 两阶段提交协议(2PC)
在 Spring Boot 和 Spring Cloud 环境中,可以使用 Seata 或 Atomikos 来实现两阶段提交协议(2PC)。以下是使用 Atomikos 和 Seata 的配置示例。
使用 Atomikos 实现两阶段提交协议(2PC):
配置数据源和 Atomikos:
在 application.yml 文件中配置 Atomikos 相关的设置:
# application.yml
spring:
datasource:
primary:
url: jdbc:mysql://localhost:3306/mydb
username: root
password: password
driver-class-name: com.mysql.cj.jdbc.Driver
secondary: