当前位置:首页 > 科技  > 软件

阿里二面:消息队列的事务消息可以用 TCC 模式实现吗?

来源: 责编: 时间:2023-10-24 08:59:58 199观看
导读大家好,我是君哥。消息队列的主要功能是系统间解耦,实现流量的削峰填谷。主流的消息队列一般有三个核心操作:消费者发送消息,Broker 保存消息,消费者消费消息。如下图:图片对于一个完整的事务消息,可以理解为生产者生产消息

大家好,我是君哥。pHb28资讯网——每日最新资讯28at.com

消息队列的主要功能是系统间解耦,实现流量的削峰填谷。主流的消息队列一般有三个核心操作:消费者发送消息,Broker 保存消息,消费者消费消息。如下图:pHb28资讯网——每日最新资讯28at.com

图片图片pHb28资讯网——每日最新资讯28at.com

对于一个完整的事务消息,可以理解为生产者生产消息和消费者消费消息,这两个操作要不全部成功要不全部失败。但事实上,很难有消息队列来实现生产消息和消费消息的事务特性。pHb28资讯网——每日最新资讯28at.com

1 事务消息实现

1.1 生产者事务

一些消息队列在生产端实现事务消息,对生产的一批消息要不全部发送成功,要不全部发送失败。pHb28资讯网——每日最新资讯28at.com

下图是 RabbitMQ 的事务消息:pHb28资讯网——每日最新资讯28at.com

图片图片pHb28资讯网——每日最新资讯28at.com

RabbitMQ 的事务消息实现的就是生产者的事务消息,发送消息的时候,把 Channel 设置为事务模式,这样这一批消息就会缓存在 Channel,等提交事务时才会提交到 Broker。可以参考下面代码:pHb28资讯网——每日最新资讯28at.com

ConnectionFactory factory=new ConnectionFactory();cnotallow=factory.newConnection();Channel channel=connection.createChannel();//开启事务channel.txSelect();channel.basicPublish("directTransactionExchange","transactionRoutingKey",null,message.getBytes("utf-8"));//提交事务 或者 channel.txRollback()回滚事务channel.txCommit();

Kafka 的事务消息类似,指定一个事务 id,集群中不同的生产者都可以使用这个事务 id 来实现事务消息。看下面代码:pHb28资讯网——每日最新资讯28at.com

String transactionId = "xxxx123yyy"Properties properties = new Properties();properties.put(ProducerConfig.TRANSACTIONAL_ID_CONFIG, transactionId);KafkaProducer<String, String> producer = new KafkaProducer<String, String>(properties);//开启事务消息producer.initTransactions();producer.beginTransaction();try {     //发送消息     String topic = "testTransactionId"     producer.send(new ProducerRecord<String, String>(topic, "msg1"));     producer.send(new ProducerRecord<String, String>(topic, "msg2"));     producer.send(new ProducerRecord<String, String>(topic, "msg3"));     // 提交事务     producer.commitTransaction();} catch (ProducerFencedException e) {     producer.abortTransaction();}producer.close();

使用同一个事务 id 后,集群中的多个生产者可以实现对不同 Topic、不同分区的原子性写入。在提交事务之前,这些消息是不可见的,事务提交之后,这些消息才能变为可见。pHb28资讯网——每日最新资讯28at.com

1.2 生产者+本地事务

生产者加本地事务也是消息队列事务消息的一种实现方式。这种事务是指本地事务和生产者生产消息是一个原子性操作,要不都成功,要不都失败。如下图所示:pHb28资讯网——每日最新资讯28at.com

图片图片pHb28资讯网——每日最新资讯28at.com

RocketMQ 的事务消息是首先发送 half 消息到 Broker,然后执行本地事务,最后执行 commit/rollback 操作。执行了 commit 操作后,消费者就可以拉取到这条消息了。如下图:pHb28资讯网——每日最新资讯28at.com

图片图片pHb28资讯网——每日最新资讯28at.com

RocketMQ 的 half 消息是将消息投递到 topic 为 RMQ_SYS_TRANS_HALF_TOPIC 中 queueId 等于 0 的队列中,当 RocketMQ 发送 commit 消息后再把消息投递到原始队列,这样消费者就可以拉取到这条消息了。pHb28资讯网——每日最新资讯28at.com

2 TCC 模式

从上面的讲解可以看到,消息队列的事务消息使用的是两阶段提交的方式。那跟 TCC 模式的两阶段提交有什么区别呢?这节我们来看一下 TCC 模式。pHb28资讯网——每日最新资讯28at.com

2.1 TCC 概述

TCC 模式将分布式事务分为 try 和 commit/rollback 两个阶段来执行,try 阶段对每个分支事务进行预留资源,如果 try 阶段所有节点都执行成功,则进入 commit 阶段提交全局事务,只要有一个节点执行失败则进入 rollback 阶段回滚全局事务。pHb28资讯网——每日最新资讯28at.com

TCC 模式有三个角色,TM、RM 和 TC:pHb28资讯网——每日最新资讯28at.com

  • TC: 协调节点,保存分支事务元数据和状态,对分支事务发送提交或回滚命令;
  • TM:管理全局事务,包括开启全局事务,提交/回滚全局事务;
  • RM:管理分支事务,包括提交或回滚本地事务,向 TC 注册分支事务并上报分支事务状态。

以购物场景中保存订单、扣减库存、扣减金额的例子来讲,try 阶段如下图:pHb28资讯网——每日最新资讯28at.com

图片图片pHb28资讯网——每日最新资讯28at.com

commit/rollback 阶段如下图:pHb28资讯网——每日最新资讯28at.com

图片图片pHb28资讯网——每日最新资讯28at.com

可以看到,TCC 模式的两阶段提交,第一阶段是用来尝试预留资源,第二阶段来扣减资源或释放资源。而消息队列中生产消息、保存消息、消费消息是不需要预留资源的,这是完全不同的业务场景。pHb28资讯网——每日最新资讯28at.com

3 总结

本文主要讲述了消息队列中的事务消息跟分布式事务中两阶段提交的 TCC 模式在实现方式上的区别。TCC 模式中两阶段提交的目的主要是用来确定资源是否可用,而消息队列的事务消息是不需要考虑资源的,二者是不同的业务场景。pHb28资讯网——每日最新资讯28at.com


pHb28资讯网——每日最新资讯28at.com

本文链接:http://www.28at.com/showinfo-26-14730-0.html阿里二面:消息队列的事务消息可以用 TCC 模式实现吗?

声明:本网页内容旨在传播知识,若有侵权等问题请及时与本网联系,我们将在第一时间删除处理。邮件:2376512515@qq.com

上一篇: Redis中万金油的String,为什么不好用了?

下一篇: IntelliJ IDEA 2023.2正式发布,新UI和Profiler转正

标签:
  • 热门焦点
Top