【RocketMQ分布式事务消息、RocketMQ分布式事务的发展流程、RocketMQ分布式事务二阶段提交解决方案、分布式案例实操学习、RocketMQ分布式事务使用场景以及注意事项】

本文详细解析了RocketMQ在分布式事务中的应用,介绍了从单体到微服务架构的发展流程,重点讲解了两阶段提交的解决方案,包括半事务阶段、确认阶段,以及生产者和消费者案例实战。同时涵盖了注意事项和最佳实践,如事务消息限制和回查机制。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

一.知识回顾

【0.RocketMQ专栏的内容在这里哟,帮你整理好了,更多内容持续更新中】
【1.Docker安装部署RocketMQ消息中间件详细教程】
【2.RocketMQ生产者发送消息的三种方式:发送同步消息、异步消息、单向消息&案例实战&详细学习流程】
【3.RocketMQ消费者进行消费消息的二种方式:集群消费、广播消费&案例实战&详细学习流程&集群消费模、广播模式的适用场景&注意事项】
【4.RocketMQ中的顺序消息、生产者顺序生产消息、消费者顺序消费消息、顺序包括全局有序和分块有序、代码样例实战】
【5.RocketMQ中延时消息的生产与消费、批量消息的生产与消费、消息的过滤、消息的Tag过滤和SQL过滤、SQL过滤解决SQL92问题,代码样例实战】

二.RocketMQ分布式事务的发展流程

2.1 举个栗子来说明分布式事务发展的来龙去脉

业务场景:用户A转账100元给用户B,具体的步骤:
1、用户A的账户先扣除100元
2、再把用户B的账户加100元
如果在同一个数据库中进行,事务可以保证这两步操作,要么同时成功,要么同时不成功。这样就保证了转账的数据一致性。如下图所示:
在这里插入图片描述

但是在微服务架构中因为各个服务都是独立的模块,都是远程调用,没法在同一个事务中,所以就会遇到分布式事务问题。如下图所示:

在这里插入图片描述

2.2 从单体架构的事务向微服务架构事务的发展流程

在这里插入图片描述

三.RocketMQ分布式事务处理流程

3.1 通过上面的案例来学习分布式事务存在的问题

在这里插入图片描述

RocketMQ分布式事务方式:把扣款业务和加钱业务异步化,扣款成功后,发送“扣款成功消息”到RocketMQ,加钱业务订阅“扣款成功消息”,再对用户B加钱(扣款消息中包含了源账户和目标账户ID,以及钱数)
对于扣款业务来说,需规定是先扣款还是先向MQ发消息
场景一:先扣款,后向MQ发消息
先扣款再发送消息,万一发送消息失败了,那用户B就没法加钱,存在问题。
场景二:先向MQ发像消息,后扣款
扣款成功消息发送成功,但用户A扣款失败,可加钱业务订阅到了消息,用户B加了钱,同样存在问题。

3.2 RocketMQ解决分布式事务的方案(俩阶段提交)

3.2.1 分析原因,痛点所在

通过上面我们的分析知道问题所在:也就是没法保证扣款和发送消息,同时成功,或同时失败;导致数据不一致。 为了解决以上问题,RocketMq把消息分为两个阶段:半事务阶段和确认阶段。

3.2.2 俩阶段提交—半事务阶段:

半事务阶段主要发一个消息到RocketMQ中,但该消息只储存在commotlog文件当中,但ConsumeQueue中不可见,也就是消费端无法看到此消息。

3.2.3 俩阶段提交—确认阶段(commit/rollback):

确认阶段主要是把半事务消息保存到ConsumeQueue中,即让消费端可以看到此消息,也就是可以消费此消息。如果是rollback就不保存。

3.2.4 俩阶段提交的整个流程

在这里插入图片描述

整个流程如下:

  1. A在扣款之前,先发送半事务消息
  2. 发送预备消息成功后,执行本地扣款事务
  3. 扣款成功后,再发送确认消息
  4. B消息端(加钱业务)可以看到确认消息,消费此消息,进行加钱业务逻辑

确认消息注意事项:

  1. 确认消息可以为Commit消息,可以被订阅者消费;
  2. 也可以是Rollback消息,即执行本地扣款事务失败后,提交Rollback消息,即删除那个半事务消息,订阅者无法消费。

   Rollback可以解决以下问题:

  • 问题1:如果发送半事务消息失败,下面的流程不会走下去,这个是正常的。
  • 问题2:如果发送半事务消息成功,但执行本地事务失败。这个也没有问题,因为此半事务消息不会被消费端订阅到,消费端不会执行业务。(后续的Rollback事务回查也可以解决这个问题,如果本地事务没有执行成功,RocketMQ回查业务,发现没有执行成功,就会发送RollBack确认消息,把消息进行删除。)

   Rollback不可以解决的问题:

  • 问题1:如果发送半事务消息成功,并且执行本地事务成功,但发送确认消息失败了,这个就有问题了,因为用户A扣款成功了,但加钱业务没有订阅到A发送来的确认消息,就无法完成加钱的业务逻辑。这里出现了数据不一致。

解决方案:
RocketMQ解决上面问题的核心思路就是通过事务回查,也就是RocketMQ会定时遍历commitlog中的半事务消息。
对于上述的问题,发送半事务消息成功,本地扣款事务成功,但发送确认消息失败;因为RocketMQ会进行回查半事务消息,在回查后发现业务已经扣款成功了,就补发发送commit确认消息;这样加钱业务就可以订阅此消息了。
在这里插入图片描述
消费端进行消息消费的时候需要注意的点:

  1. RocketMQ不能保障消息的重复,所以在消费端一定要做幂等性处理。
  2. 如果消费端发生消费失败,同时也需要做重试,如果重试多次,消息会进入死信队列,这个时候也需要进行特殊的处理。(一般就是把A已经处理完的业务进行回退)
3.2.5 事务回查的流程?或者说事务回查找的是哪张表呢?有没有什么好的解决方案呢?

背景分析:如果本地事务执行了很多张表,难道我们需要对所有表都要进行判断是否执行成功呢?这样的操作不仅效率慢,而且都是再做同样的事情,耦合度过高。那我们该怎么解决呢?方案如下:

在这里插入图片描述

解决方案:
设计一张Transaction表,将业务表和Transaction绑定在同一个本地事务中,如果扣款本地事务成功,Transaction中应当已经记录该TransactionId的状态为【已完成】。当RocketMQ事务回查时,只需要检查对应的TransactionId的状态是否是【已完成】就好,而不用关心具体的业务数据。

四.光说不练假把式~~~分布式事务实战学习

4.1 生产者案例代码

/**
 * A系统---消息生产者
 */
public class TransactionProducer {
    public static void main(String[] args) throws MQClientException, InterruptedException {
        //创建事务监听器,对我们的事务进行监听,需要负责执行本地事务以及一些事务的回查操作
        TransactionListener transactionListener = new TransactionListenerImpl();
        TransactionMQProducer producer = new TransactionMQProducer("TransactionProducer");
        producer.setNamesrvAddr("121.5.139.205:9876");
        //创建线程池
        ExecutorService executorService = new ThreadPoolExecutor(4, 8, 100, TimeUnit.SECONDS, new ArrayBlockingQueue<Runnable>(2000), new ThreadFactory() {
            @Override
            public Thread newThread(Runnable r) {
                Thread thread = new Thread(r);
                thread.setName("client-transaction-msg-check-thread");
                return thread;
            }
        });
        //设置生产者回查线程池
        producer.setExecutorService(executorService);
        //生产者设置监听器
        producer.setTransactionListener(transactionListener);
        //启动消息生产者
        producer.start();
        //1、半事务的发送
        try {
            Message msg = new Message("TransactionTopic", null, ("A向B系统转1314元").getBytes(RemotingHelper.DEFAULT_CHARSET));
            SendResult sendResult = producer.sendMessageInTransaction(msg, null);
            SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");//设置日期格式
            System.out.println(sendResult.getSendStatus()+"-"+df.format(new Date()));//半事务消息是否成功
        } catch (MQClientException | UnsupportedEncodingException e) {
            //TODO 如果半事务还没有提交成功,那么直接ROllback
            //LocalTransactionState.ROLLBACK_MESSAGE;
            e.printStackTrace();
        }
        //2、半事务的发送成功
        //一些长时间等待的业务,需要通过事务回查来处理
        for (int i = 0; i < 100; i++) {
            Thread.sleep(1000);
        }
        producer.shutdown();
    }
}

/*
* 事务监听类
*/
class TransactionListenerImpl implements TransactionListener {
    //执行本地事务
    @Override
    public LocalTransactionState executeLocalTransaction(Message msg, Object arg) {
        SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");//设置日期格式
        //TODO 执行本地事务 update A...
        System.out.println("update A ... where transactionId:"+msg.getTransactionId() +":"+df.format(new Date()));
        //todo 情况1:本地事务成功
        //return LocalTransactionState.COMMIT_MESSAGE;
        //TODO 情况2:本地事务失败
        //System.out.println("rollback");
        //return LocalTransactionState.ROLLBACK_MESSAGE;
        //TODO 情况3:业务复杂,还处于中间过程或者依赖其他操作的返回结果,UNKNOW
        System.out.println("业务比较复杂,没有处理完,无法确定是Success >or< Fail!");
        return LocalTransactionState.UNKNOW;
    }
    //事务回查  默认是60s,一分钟检查一次
    @Override
    public LocalTransactionState checkLocalTransaction(MessageExt msg) {
        //打印每次回查的时间
        SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");//设置日期格式
        System.out.println("checkLocalTransaction:"+df.format(new Date()));// new Date()为获取当前系统时间
        //TODO 情况3.1:业务回查成功!
        System.out.println("业务回查:执行本地事务成功,确认消息");
        return LocalTransactionState.COMMIT_MESSAGE;
        //TODO 情况3.2:业务回查回滚!
        //System.out.println("业务回查:执行本地事务失败,删除消息");
        //return LocalTransactionState.ROLLBACK_MESSAGE;
        //TODO 情况3.3:业务回查还是UNKNOW!
        //System.out.println("业务比较复杂,没有处理完,无法确定是Success >or< Fail!");
        //return LocalTransactionState.UNKNOW;
    }
}


4.2 消费者案例代码

/**
 * 事务消息-消费者 B
 */
public class TranscationComuser {
    public static void main(String[] args) throws Exception {
        DefaultMQPushConsumer consumer = new DefaultMQPushConsumer("TranscationComsuer");
        consumer.setNamesrvAddr("121.5.139.205:9876");
        consumer.subscribe("TransactionTopic", "*");
        consumer.setMessageModel(MessageModel.CLUSTERING);
        consumer.registerMessageListener(new MessageListenerConcurrently() {
            @Override
            public ConsumeConcurrentlyStatus consumeMessage(List<MessageExt> msgs,
                                                            ConsumeConcurrentlyContext context) {
                try {
                    //todo  开启事务
                    for(MessageExt msg : msgs) {
                        //todo 执行本地事务 update B...(幂等性)
                        System.out.println("update B ... where transactionId:"+msg.getTransactionId());
                        //todo 本地事务成功
                        System.out.println("commit:"+msg.getTransactionId());
                        System.out.println("执行本地事务成功,确认消息");
                    }
                } catch (Exception e) {
                    e.printStackTrace();
                    System.out.println("执行本地事务失败,重试消费,尽量确保B处理成功");
                    return ConsumeConcurrentlyStatus.RECONSUME_LATER;
                }
                return ConsumeConcurrentlyStatus.CONSUME_SUCCESS;
            }
        });
        //启动消息者
        consumer.start();
        System.out.printf("Consumer Started.%n");
    }
}

4.3 运行结果

在这里插入图片描述

在这里插入图片描述

五.RocketMQ分布式事务使用的注意事项

  1. 事务消息不支持延时消息和批量消息。
  2. 通过Broker的配置文件可以配置事务回查的间隔时间:BrokerConfig. transactionCheckInterval。
  3. 为了避免单个消息被检查太多次而导致半队列消息累积,我们默认将单个消息的检查次数限制为 15 次,但是用户可以通过 Broker 配置文件的 transactionCheckMax参数来修改此限制。如果已经检查某条消息超过 N 次的话( N = transactionCheckMax ) 则 Broker 将丢弃此消息,并在默认情况下同时打印错误日志。用户可以通过重写 AbstractTransactionCheckListener 类来修改这个行为。
  4. 事务消息将在 Broker 配置文件中的参数 transactionMsgTimeout 这样的特定时间长度之后被检查。当发送事务消息时,用户还可以通过设置用户属性 CHECK_IMMUNITY_TIME_IN_SECONDS 来改变这个限制,该参数优先于 transactionMsgTimeout 参数。
  5. 事务性消息可能不止一次被检查或消费。
  6. 事务性消息中用到了生产者群组,这种就是一种高可用机制,用来确保事务消息的可靠性。
  7. 提交给用户的目标主题消息可能会失败,目前这依日志的记录而定。它的高可用性通过 RocketMQ 本身的高可用性机制来保证,如果希望确保事务消息不丢失、并且事务完整性得到保证,建议使用同步的双重写入机制。
  8. 事务消息的生产者 ID 不能与其他类型消息的生产者 ID 共享。与其他类型的消息不同,事务消息允许反向查询、MQ服务器能通过它们的生产者 ID 查询到消费者。

好了,到这里【RocketMQ分布式事务消息、RocketMQ分布式事务的发展流程、RocketMQ分布式事务二阶段提交解决方案、分布式案例实操学习、RocketMQ分布式事务使用场景以及注意事项】就先学习到这里,关于RocketMQ更多知识,持续学习创作中。

<think>好的,我需要帮这位用户制定一个详细的学习计划,目标是在一年内从有1年CRUD经验的Java开发者成长为阿里P6级架构师。用户每天最多能投入6小时,偏好项目驱动学习,需要包含AI和高并发设计能力。首先,我得分析阿里P6架构师的要求,然后结合用户当前水平,制定合理的阶计划。 首先,P6架构师通常需要扎的Java基础、系统设计能力、高并发处理经验、分布式系统知识,以及一定的技术领导力。用户提到还没完全掌握Java基础,这可能是第一个需要加强的地方。虽然用户有一年CRUD经验,但可能需要深入理解JVM、多线程、框架原理等。 接下来,项目驱动学习是关键。用户偏好通过项目来学习,所以每个阶都应该有际的项目来应用所学知识。同时,AI和高并发是重点,需要将这两个领域融入项目中。 考虑到时间安排,一年大约52周,可以分为几个阶:打基础、进阶提升、系统设计、架构战、AI整合、综合强化。每个阶大约8-10周,逐步深入。 第一阶需要巩固Java基础,包括JVM、集合框架、多线程、IO/NIO、反射和设计模式。同时开始接触高并发的基础,比如锁机制、线程池。每周安排理论学习加小项目,比如用多线程实现爬虫,确保基础扎。 第二阶进阶,学习Spring框架原理、分布式系统基础(CAP理论、服务发现、负载均衡)、数据库优化(索引、分库分表)、消息队列(Kafka、RocketMQ)。项目方面可以设计一个分布式电商系统,应用这些技术。 第三阶系统设计,学习微服务架构(Spring Cloud、Dubbo)、容器化(Docker、K8s)、高并发设计(限流、熔断、降级)、缓存策略(Redis集群、分布式锁)。项目可以是一个高并发的秒杀系统,使用这些技术解决际问题。 第四阶架构战,深入分布式事务、分库分表中间件、监控系统(Prometheus、SkyWalking)、压力测试(JMeter)。项目可以是全链路压测平台,整合之前的技能,进行性能优化。 第五阶整合AI,学习机器学习基础、TensorFlow/PyTorch、推荐系统、自然语言处理。项目方面,可以做一个基于用户行为的推荐系统,或者智能客服系统,将AI融入后端服务。 最后阶综合强化,复习所有内容,模拟面试,参与开源项目,总结项目经验。同时准备架构设计案例,提升沟通和团队协作能力。 需要确保每周有明确的学习目标和验证方式,比如代码Review、压力测试结果、项目部署等。技术验证方案要包括代码审查、压测报告、线上问题排查、架构图设计、数据评估和面试模拟,确保每一步都有际成果。 可能遇到的问题包括时间安排过紧,导致某些阶无法深入,或者项目复杂度高难以完成。因此,每个阶的项目需要合理设计,既挑战又可行,逐步提升难度。同时,保持持续的学习和反馈,及时调整计划。</think>我将为您拆解为期52周的分阶成长计划(附技术验证方案)。以下为符合P6能力模型的核心技术栈及学习路径: --- ### **一、基础夯(Week 1-8)** **目标**:补足Java核心短板 + 构建高并发认知框架 **每日投入**:2小时基础 + 1小时并发 + 3小时项目 ```markdown Week 1-2: - 核心重点:JVM内存模型/GC算法/字节码增强技术(Javassist) - 高并发基础:synchronized锁升级过程/CAS底层实现 - 验证项目:实现线程安全的高速缓存库(对比HashMap/ConcurrentHashMap性能) Week 3-4: - 源码级理解:AQS体系(ReentrantLock/Semaphore源码走读) - 网络编程:Netty核心线程模型(Boss-Worker分组践) - 验证项目:基于Netty实现HTTP压测工具(对比Tomcat线程模型) Week 5-6: - 存储层优化:MySQL索引实现原理(B+树解析) - 分布式基石:Paxos算法推导(自制简易分布式锁服务) - 验证项目:设计分库分表路由中间件(支持一致性哈希策略) Week 7-8: - 消息队列:Kafka ISR机制与零拷贝实现 - 性能调优:Arthas诊断线程死锁/JVM内存泄漏 - 验证项目:搭建订单超时取消系统(Kafka延迟队列+Redis过期监听) ``` --- ### **二、架构设计阶(Week 9-20)** **目标**:掌握复杂系统设计方法论 + 构建高可用架构思维 **每日投入**:2小时原理 + 2小时设计 + 2小时战 ```markdown Week 9-12:微服务架构 - 服务治理:Dubbo SPI扩展机制/Spring Cloud Alibaba体系对比 - 容错设计:Sentinel熔断规则动态配置战 - 验证项目:搭建电商系统(服务拆分/分布式事务/灰度发布) Week 13-16:高并发体系 - 流量控制:令牌桶/漏桶算法在Sentinel中的实现差异 - 缓存策略:Redis多级缓存架构(Caffeine+Redis+本地缓存) - 验证项目:设计秒杀系统(库存预热/限流削峰/扣减防超卖) Week 17-20:云原生架构 - 容器编排:K8s Operator开发践(自定义CRD) - 服务网格:Istio流量镜像在压测场景中的应用 - 验证项目:构建A/B测试平台(Envoy Filter+Prometheus监控) ``` --- ### **三、AI工程化阶(Week 21-32)** **目标**:实现传统系统与AI能力融合 **每日投入**:3小时算法 + 2小时工程 + 1小时调优 ```markdown Week 21-24:基础能力建设 - 机器学习:特征工程处理(使用Apache Spark处理TB级日志) - 模型部署:TensorFlow Serving动态加载模型践 - 验证项目:用户画像系统(Flink时特征计算+LR模型预测) Week 25-28:智能决策系统 - 强化学习:Q-Learning在库存调度中的践 - 模型优化:ONNX格式转换与推理加速 - 验证项目:智能客服系统(BERT意图识别+规则引擎融合) Week 29-32:大规模推理优化 - 异构计算:GPU资源池化方案(K8s Device Plugin开发) - 服务治理:模型版本热更新与流量切换 - 验证项目:搭建推荐系统(召回排序链路全流程实现) ``` --- ### **四、综合战阶(Week 33-52)** **目标**:全链路架构设计 + 技术影响力建设 **每日投入**:3小时复杂系统设计 + 2小时源码研究 + 1小时输出 ```markdown Week 33-36:混沌工程体系 - 建设故障注入平台(基于ChaosBlade扩展自定义场景) - 验证项目:实现自动化的容灾演练系统 Week 37-40:架构演进设计 - 分析淘宝单元化架构演进路径 - 验证项目:设计异地多活方案(数据同步冲突解决策略) Week 41-44:性能极致优化 - JIT编译优化分析(使用JITWatch研究热点代码) - 验证项目:实现百万QPS网关(DPDK+用户态协议栈) Week 45-52:技术影响力塑造 - 输出3篇深度技术文章(发表在InfoQ/阿里云社区) - 参与开源项目贡献(如Apache Dubbo/Sentinel) - 构建个人技术雷达图(定期更新技术认知地图) ``` --- ### **五、技术验证方案** 1. **代码级验证** - 每周Git提交可运行的核心代码 - 关键算法实现需通过LeetCode Hard级别测试用例 $$T(n) \leq O(n \log n) \text{ 需数学证明复杂度}$$ 2. **压力测试标准** - 高并发系统需达到: $$QPS \geq 10万 \quad \text{且} \quad P99 \leq 50ms$$ 使用JMeter生成测试报告并分析火焰图 3. **线上问题诊断** - 每月模拟1次生产事故(CPU飙高/Full GC频繁) - 输出包含根本原因分析(RCA)的完整报告 4. **架构设计评审** - 每阶输出系统架构图(使用C4模型规范) - 通过SWOT分析法评估技术选型 5. **AI效果评估** - 分类模型需达到: $$\text{F1-score} \geq 0.85 \quad \text{在测试集上}$$ - 推荐系统CTR提升需有AB测试数据支撑 --- ### **六、学习资源推荐** 1. 源码级教材:《深入理解Java虚拟机(第三版)》 2. 架构范式:《数据密集型应用系统设计》 3. 工程践:《Kubernetes in Action》 4. AI工程:《机器学习系统设计》(附真案例代码) 建议每周日进行2小时学习复盘,使用OKR工具跟踪进展。关键是要建立「设计-实现-压测-优化」的完整闭环,这将直接符合阿里P6要求的「复杂问题系统性解决能力」。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

硕风和炜

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值