RocketMQ 与 Spring Cloud Stream之事务消息配置

1 引言

RocketMQ的事务消息设计是为了解决分布式系统中数据一致性的问题。在分布式系统中,由于数据可能分布在不同的服务或节点上,因此需要一种机制来确保数据的最终一致性。事务消息通过引入本地事务和消息状态的关联,确保了消息的发送与本地事务的执行结果紧密相关,从而避免了数据不一致的问题。

2 事务消息步骤

  1. 生产者将半事务消息发送至 RocketMQ Broker。
  2. RocketMQ Broker 将消息持久化成功之后,向生产者返回 Ack 确认消息已经发送成功,此时消息暂不能投递,为半事务消息。
  3. 生产者开始执行本地事务逻辑。
  4. 生产者根据本地事务执行结果向服务端提交二次确认结果(Commit或是Rollback),服务端收到确认结果后处理逻辑如下:
    4.1 二次确认结果为Commit:服务端将半事务消息标记为可投递,并投递给消费者。
    4.2 二次确认结果为Rollback:服务端将回滚事务,不会将半事务消息投递给消费者。
  5. 在断网或者是生产者应用重启的特殊情况下,若服务端未收到发送者提交的二次确认结果,或服务端收到的二次确认结果为Unknown未知状态,经过固定时间后,服务端将对消息生产者即生产者集群中任一生产者实例发起消息回查。
    5.1 生产者收到消息回查后,需要检查对应消息的本地事务执行的最终结果。
    5.2 生产者根据检查得到的本地事务的最终状态再次提交二次确认,服务端仍按照步骤4对半事务消息进行处理。
  6. 注意:服务端仅仅会按照参数尝试指定次数,超过次数后事务会强制回滚,因此未决事务的回查时效性非常关键,需要按照业务的实际风险来设置。

3 项目结构

本章内容以Spring Cloud Alibaba 快速学习之 RocketMQ中的项目为基础稍作修改。下面列出修改的文件。

3.1 项目rocketmq-producer

在这里插入图片描述

  • application.properties
    这里添加了事务相关的配置
 #spring应用程序监听的端口号
server.port=8080
#spring应用程序的名称
spring.application.name=rocketmq-producer
#spring当前激活的配置文件
spring.profiles.active=dev

#rocketmq 服务地址
spring.cloud.stream.rocketmq.binder.name-se
Spring Cloud Stream 中,StreamBridge.send 方法默认是单线程的,因为它使用了 Spring Integration 的消息通道,而 Spring Integration 的消息通道默认是单线程的。但是,你可以通过配置 Spring Integration 的任务执行器来改变这个行为,使其变成多线程的。 具体实现方式如下: 1. 在 `application.properties` 中配置任务执行器: ``` spring.task.execution.pool.core-size=10 spring.task.execution.pool.max-size=20 spring.task.execution.pool.queue-capacity=1000 spring.integration.taskScheduler.poolSize=10 ``` 其中,`spring.task.execution.pool.core-size`、`spring.task.execution.pool.max-size` 和 `spring.task.execution.pool.queue-capacity` 是线程池的核心线程数、最大线程数和队列容量。`spring.integration.taskScheduler.poolSize` 是 Spring Integration 的任务调度器的线程池大小。 2. 注入 `TaskExecutor` 并使用它来发送消息: ```java @Autowired private TaskExecutor taskExecutor; @Autowired private StreamBridge streamBridge; public void sendMessageAsync(String message) { taskExecutor.execute(() -> { streamBridge.send("myDestination", message); }); } ``` 在这个示例中,我们注入了 `TaskExecutor`,并使用它来异步发送消息。在发送消息的过程中,我们使用了 Lambda 表达式来创建一个新的线程,然后在这个新线程中调用 `streamBridge.send` 方法发送消息。 需要注意的是,使用多线程发送消息时需要注意线程安全和性能问题,特别是线程池的大小和队列容量需要根据实际情况进行调整,否则可能会出现线程阻塞、内存溢出等问题。因此建议在具体的项目中,根据实际情况选择使用单线程或多线程发送消息
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值