分布式事务总结

分布式事务

1.基本概念CAP原理 P一定存在,一般追求CP强一致性或者AP高可用。 AP追求高可用,软一致,base原来,软一致性,或者最终一致性。 BASE 是 Basically Available(基本可用)、Soft state(软状态)和 Eventually consistent (最终一致性)三个短语的缩写。是对CAP中AP的一个扩展 CP 强一致性,基于XA协议,事务协调者和事务参与者,有两阶段提交(seata模式) 三阶段提交。无论两阶段还是三阶段都不能完全保证数据一致性。异常都需要人工干预。

两阶段基于数据库的undolog 和redolog日志实现,第一阶段 AP:消息队列的最终一致性。 rocketMq 消息队列的最终一致性,允许短暂超卖。 不需要强一致性的场景,订单-短信服务/订单-物流服务 生产者先发送一个半消息,对消费者不可见,本地事务执行完成后,对消息进行确认,消费者消费消息,会有重试机制。

  1. 半消息发送:消息先发送到MQ,但对消费者不可见。

  2. 本地事务执行:生产者执行本地事务(如创建订单)。

  3. 提交/回滚消息

    • 若事务成功 → MQ将消息标记为可消费。
    • 若事务失败 → MQ删除消息。
  4. 消息投递:仅当事务成功时,消费者才能处理消息。 消费者需要注意幂等性校验,消费者重试机制,重试多次后进入死信队列,人工介入。

`#### 1. 生产者初始化

csharp 复制代码
Java
1public class OrderService {
2    private TransactionMQProducer producer;
3
4    public void init() throws MQClientException {
5        // 创建事务消息生产者
6        producer = new TransactionMQProducer("order_producer_group");
7        producer.setNamesrvAddr("localhost:9876");
8        
9        // 绑定事务监听器(核心事务逻辑入口)
10        producer.setTransactionListener(new OrderTransactionListener(this));
11        
12        // 启动生产者
13        producer.start();
14    }
15}
  • 关键点 :通过 setTransactionListener 绑定事务监听器 OrderTransactionListener,用于后续处理本地事务和状态回查。

2. 发送事务消息(半消息)

java 复制代码
Java
1public void createOrderTransaction(OrderDTO order) throws MQClientException {
2    // 构建消息(Topic、Tag、Key、Body)
3    Message msg = new Message(
4        "order_topic", 
5        "order_tag", 
6        order.getOrderId(),
7        JSON.toJSONBytes(order)
8    );
9    
10    // 发送事务消息(触发半消息机制)
11    TransactionSendResult result = producer.sendMessageInTransaction(msg, order);
12    
13    // 检查事务状态(此处为同步调用结果,非最终消息状态)
14    if (result.getLocalTransactionState() != LocalTransactionState.COMMIT_MESSAGE) {
15        throw new RuntimeException("事务可能已回滚!");
16    }
17}
  • 关键点producer.sendMessageInTransaction(msg, order) 触发以下流程:

    1. 半消息发送 :消息被发送到 RocketMQ Broker,但对消费者不可见(状态为 HALF_MESSAGE)。
    2. 执行本地事务 :自动调用 OrderTransactionListener.executeLocalTransaction()

3. 本地事务执行与消息确认(核心逻辑)

typescript 复制代码
Java
1public class OrderTransactionListener implements TransactionListener {
2    private OrderService orderService;
3
4    @Override
5    public LocalTransactionState executeLocalTransaction(Message msg, Object arg) {
6        // 解析业务参数(arg 即发送消息时传入的 order 对象)
7        OrderDTO order = (OrderDTO) arg;
8        
9        try {
10            // --------------------------------
11            // 本地事务提交(如订单入库)
12            // --------------------------------
13            boolean success = orderService.createOrder(order);
14            
15            // 根据事务结果返回状态(提交或回滚消息)
16            return success ? LocalTransactionState.COMMIT_MESSAGE 
17                           : LocalTransactionState.ROLLBACK_MESSAGE;
18        } catch (Exception e) {
19            return LocalTransactionState.ROLLBACK_MESSAGE;
20        }
21    }
22
23    @Override
24    public LocalTransactionState checkLocalTransaction(MessageExt msg) {
25        // 事务状态回查(兜底逻辑)
26        String orderId = msg.getKeys();
27        boolean exists = orderService.orderExists(orderId);
28        return exists ? LocalTransactionState.COMMIT_MESSAGE 
29                     : LocalTransactionState.ROLLBACK_MESSAGE;
30    }
31}`
  • 关键点

    • executeLocalTransaction

      • 触发时机 :在 sendMessageInTransaction 发送半消息后立即执行
      • 作用 :执行本地事务(如订单入库),并根据结果决定提交(COMMIT_MESSAGE)或回滚(ROLLBACK_MESSAGE)消息。
    • checkLocalTransaction

      • 触发时机:若生产者崩溃未返回事务状态,RocketMQ 会主动调用此方法回查状态。
      • 作用:检查本地事务是否已提交(如查询订单是否存在),确保最终一致性。

4. RocketMQ Broker 处理消息

根据 LocalTransactionState 的返回值,Broker 执行以下操作:

  • COMMIT_MESSAGE:将半消息标记为可消费状态(对消费者可见)。
  • ROLLBACK_MESSAGE:删除半消息,避免无效投递。
  • UNKNOW:等待下一次回查(默认间隔 1 分钟)

CAP定理,又被叫作布鲁尔定理。对于设计分布式系统来说(不仅仅是分布式事务)的架构师来说,CAP就是你的入门理论。

  • C (一致性):对某个指定的客户端来说,读操作能返回最新的写操作。对于数据分布在不同节点上的数据上来说,如果在某个节点更新了数据,那么在其他节点如果都能读取到这个最新的数据,那么就称为强一致,如果有某个节点没有读取到,那就是分布式不一致。
  • A (可用性):非故障的节点在合理的时间内返回合理的响应(不是错误和超时的响应)。可用性的两个关键一个是合理的时间,一个是合理的响应。合理的时间指的是请求不能无限被阻塞,应该在合理的时间给出返回。合理的响应指的是系统应该明确返回结果并且结果是正确的,这里的正确指的是比如应该返回50,而不是返回40。
  • P (分区容错性):当出现网络分区后,系统能够继续工作。打个比方,这里个集群有多台机器,有台机器网络出现了问题,但是这个集群仍然可以正常工作。

熟悉CAP的人都知道,三者不能共有,如果感兴趣可以搜索CAP的证明,在分布式系统中,网络无法100%可靠,分区其实是一个必然现象,如果我们选择了CA而放弃了P,那么当发生分区现象时,为了保证一致性,这个时候必须拒绝请求,但是A又不允许,所以分布式系统理论上不可能选择CA架构,只能选择CP或者AP架构。

对于CP来说,放弃可用性,追求一致性和分区容错性,我们的zookeeper其实就是追求的强一致。

对于AP来说,放弃一致性(这里说的一致性是强一致性),追求分区容错性和可用性,这是很多分布式系统设计时的选择,后面的BASE也是根据AP来扩展。

相关推荐
倚栏听风雨9 分钟前
火焰图怎么看
后端
Moonbit14 分钟前
MoonBit Pearls Vol.12:初探 MoonBit 中的 Javascript 交互
javascript·后端·面试
摆烂工程师23 分钟前
(2025年11月)开发了 ChatGPT 导出聊天记录的插件,ChatGPT Free、Plus、Business、Team 等用户都可用
前端·后端·程序员
gongzemin33 分钟前
使用阿里云ECS部署前端应用
前端·vue.js·后端
用户83562907805137 分钟前
使用Python合并Word文档:实现高效自动化办公
后端·python
小灰灰搞电子1 小时前
Rust Slint实现控件尺寸的扩展与收缩源码分享
开发语言·后端·rust
天天摸鱼的java工程师1 小时前
八年 Java 开发手敲:SpringBoot+SpringSecurity+JWT 实战,前后分离权限注解落地就能跑
java·后端
qianbailiulimeng1 小时前
IDEA + Spring Boot 的三种热加载方案
java·后端
王元_SmallA1 小时前
网卡驱动架构以及源码分析
java·后端
八苦1 小时前
实现 json path 来评估函数式解析器的损耗
后端