目次
黑马商城 Spring Cloud 微服务课程条记:分布式事务 - Seata 的架构和原理
一、Seata 解决的问题场景
二、Seata 的架构
三、Seata 的原理
在黑马商城的微服务架构中,当涉及到多个微服务协同完成一个业务操作时,分布式事务的处置惩罚变得至关重要。此中,Seata 是一个开源的分布式事务解决方案,用于解决微服务架构中的分布式事务问题。
一、Seata 解决的问题场景
在黑马商城中,比方用户下单购买商品这个业务场景,涉及到订单服务创建订单、库存服务扣减库存、用户服务扣除积分等多个微服务操作。如果这些操作不能保证在一个事务内执行,就大概出现部门操作乐成、部门操作失败的情况,导致数据不一致。Seata 就是为了解决这种分布式事务场景下的数据一致性问题。
二、Seata 的架构
- TC(Transaction Coordinator)- 事务协调者
- 负责协调和管理全局事务,是全局事务的核心管理者。它接收事务发起者的哀求,协调各个加入者的事务执行,决定事务是提交还是回滚。
- 代码示例(伪代码,实际 Seata TC 是独立部署的服务,这里只是示意其协调逻辑):
- public class TransactionCoordinator {
- private List<TransactionParticipant> participants;
- public TransactionCoordinator(List<TransactionParticipant> participants) {
- this.participants = participants;
- }
- public void handleTransaction() {
- // 向参与者发送准备请求
- for (TransactionParticipant participant : participants) {
- participant.prepare();
- }
- // 收集参与者的准备结果
- boolean allPrepared = true;
- for (TransactionParticipant participant : participants) {
- if (!participant.isPrepared()) {
- allPrepared = false;
- break;
- }
- }
- if (allPrepared) {
- // 所有参与者准备成功,发送提交请求
- for (TransactionParticipant participant : participants) {
- participant.commit();
- }
- } else {
- // 有参与者准备失败,发送回滚请求
- for (TransactionParticipant participant : participants) {
- participant.rollback();
- }
- }
- }
- }
复制代码
- TM(Transaction Manager)- 事务管理器
- 定义全局事务的范围,开始全局事务、提交或回滚全局事务。它与业务逻辑精密联合,负责将业务操作纳入到分布式事务管理中。
- 代码示例(伪代码,假设在订单服务中利用):
- import io.seata.spring.annotation.GlobalTransactional;
- import org.springframework.stereotype.Service;
- @Service
- public class OrderService {
- @GlobalTransactional
- public void createOrder() {
- // 业务逻辑,创建订单,调用其他服务等
- // 这里的方法执行就会被Seata的TM纳入到全局事务管理中
- }
- }
复制代码
- RM(Resource Manager)- 资源管理器
- 管理分支事务的资源,如数据库毗连等。它负责向 TC 注册分支事务,报告分支事务的状态,并根据 TC 的指令执行当地事务的提交或回滚。
- 以数据库为例,假设在库存服务中利用 Seata 管理数据库事务(伪代码):
- import javax.sql.DataSource;
- import io.seata.rm.datasource.DataSourceProxy;
- import org.springframework.context.annotation.Bean;
- import org.springframework.context.annotation.Configuration;
- @Configuration
- public class SeataDataSourceConfig {
- @Bean
- public DataSource dataSource() {
- // 假设这里获取到了实际的数据源,比如DruidDataSource等
- DataSource actualDataSource = // 获取实际数据源的代码
- return new DataSourceProxy(actualDataSource);
- }
- }
复制代码 三、Seata 的原理
- 一阶段(执行当地事务并注册分支事务)
- 当业务操作开始时,TM 向 TC 发起全局事务开始哀求,TC 生成全局事务 ID 并返回给 TM。
- 各个微服务(RM)执行当地事务,在执行当地事务前,RM 会向 TC 注册分支事务,将自己纳入到全局事务管理中。
- 当地事务执行完成后,RM 会向 TC 报告当地事务的执行状态(乐成或失败)。
- 代码示例(联合前面的订单、库存服务示例,假设库存服务执行当地事务并注册分支事务):
- import io.seata.core.context.RootContext;
- import io.seata.spring.annotation.GlobalTransactional;
- import io.seata.tm.api.TransactionalExecutor;
- import org.springframework.beans.factory.annotation.Autowired;
- import org.springframework.jdbc.core.JdbcTemplate;
- import org.springframework.stereotype.Service;
- @Service
- public class StockService {
- @Autowired
- private JdbcTemplate jdbcTemplate;
- @GlobalTransactional
- public void deductStock() {
- // 获取全局事务ID
- String xid = RootContext.getXID();
- try {
- // 执行本地事务,扣减库存
- jdbcTemplate.update("UPDATE stock SET quantity = quantity - 1 WHERE product_id =?", 1);
- // 向TC注册分支事务,这里假设已经有相关的Seata客户端配置
- TransactionalExecutor.registerBranchTransaction(xid, "库存服务", null);
- } catch (Exception e) {
- // 如果本地事务执行失败,向TC报告失败状态,这里简化处理,实际可能需要更完善的错误处理
- TransactionalExecutor.reportFailure(xid, e);
- throw e;
- }
- }
- }
复制代码
- 二阶段(提交或回滚全局事务)
- 提交阶段
- 如果所有分支事务的一阶段都执行乐成并且向 TC 报告了乐成状态,TC 会向所有 RM 发送提交哀求。
- RM 收到提交哀求后,提交当地事务。
- 回滚阶段
- 如果有任何一个分支事务在一阶段执行失败或者向 TC 报告了失败状态,TC 会向所有 RM 发送回滚哀求。
- RM 收到回滚哀求后,根据一阶段记载的 undo 日志进行回滚操作,将数据恢复到事务开始前的状态。
- 代码示例(Seata 的二阶段提交和回滚操作是由 Seata 框架自动处置惩罚的,这里无法给出详细的代码实现,但可以简单示意回滚逻辑的思路,假设在库存服务中处置惩罚回滚):
- import io.seata.core.context.RootContext;
- import io.seata.spring.annotation.GlobalTransactional;
- import io.seata.tm.api.TransactionalExecutor;
- import org.springframework.beans.factory.annotation.Autowired;
- import org.springframework.jdbc.core.JdbcTemplate;
- import org.springframework.stereotype.Service;
- @Service
- public class StockService {
- @Autowired
- private JdbcTemplate jdbcTemplate;
- @GlobalTransactional
- public void deductStock() {
- String xid = RootContext.getXID();
- try {
- // 执行本地事务,扣减库存
- jdbcTemplate.update("UPDATE stock SET quantity = quantity - 1 WHERE product_id =?", 1);
- // 向TC注册分支事务等操作(前面已示例)
- } catch (Exception e) {
- // 如果本地事务执行失败,向TC报告失败状态(前面已示例)
- // 假设这里收到TC的回滚请求后,进行回滚操作
- if (TransactionalExecutor.isRollbackOnly(xid)) {
- // 根据undo日志进行回滚,这里简化为直接增加库存(实际需要根据undo日志正确恢复数据)
- jdbcTemplate.update("UPDATE stock SET quantity = quantity + 1 WHERE product_id =?", 1);
- }
- throw e;
- }
- }
- }
复制代码
Seata 通过其独特的架构和事务处置惩罚原理,为黑马商城的微服务架构提供了有效的分布式事务解决方案,确保在复杂的微服务协作场景下数据的一致性。在实际应用中,需要根据具体的业务需求和技能架构公道配置和利用 Seata。
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。 |