文章详情

短信预约-IT技能 免费直播动态提醒

请输入下面的图形验证码

提交验证

短信预约提醒成功

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

2024-11-30 05:59

关注

消息队列的主要功能是系统间解耦,实现流量的削峰填谷。主流的消息队列一般有三个核心操作:消费者发送消息,Broker 保存消息,消费者消费消息。如下图:

图片

对于一个完整的事务消息,可以理解为生产者生产消息和消费者消费消息,这两个操作要不全部成功要不全部失败。但事实上,很难有消息队列来实现生产消息和消费消息的事务特性。

1 事务消息实现

1.1 生产者事务

一些消息队列在生产端实现事务消息,对生产的一批消息要不全部发送成功,要不全部发送失败。

下图是 RabbitMQ 的事务消息:

图片

RabbitMQ 的事务消息实现的就是生产者的事务消息,发送消息的时候,把 Channel 设置为事务模式,这样这一批消息就会缓存在 Channel,等提交事务时才会提交到 Broker。可以参考下面代码:

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 来实现事务消息。看下面代码:

String transactionId = "xxxx123yyy"
Properties properties = new Properties();
properties.put(ProducerConfig.TRANSACTIONAL_ID_CONFIG, transactionId);
KafkaProducer producer = new KafkaProducer(properties);
//开启事务消息
producer.initTransactions();
producer.beginTransaction();

try {
     //发送消息
     String topic = "testTransactionId"
     producer.send(new ProducerRecord(topic, "msg1"));
     producer.send(new ProducerRecord(topic, "msg2"));
     producer.send(new ProducerRecord(topic, "msg3"));
     // 提交事务
     producer.commitTransaction();
} catch (ProducerFencedException e) {
     producer.abortTransaction();
}
producer.close();

使用同一个事务 id 后,集群中的多个生产者可以实现对不同 Topic、不同分区的原子性写入。在提交事务之前,这些消息是不可见的,事务提交之后,这些消息才能变为可见。

1.2 生产者+本地事务

生产者加本地事务也是消息队列事务消息的一种实现方式。这种事务是指本地事务和生产者生产消息是一个原子性操作,要不都成功,要不都失败。如下图所示:

图片

RocketMQ 的事务消息是首先发送 half 消息到 Broker,然后执行本地事务,最后执行 commit/rollback 操作。执行了 commit 操作后,消费者就可以拉取到这条消息了。如下图:

图片

RocketMQ 的 half 消息是将消息投递到 topic 为 RMQ_SYS_TRANS_HALF_TOPIC 中 queueId 等于 0 的队列中,当 RocketMQ 发送 commit 消息后再把消息投递到原始队列,这样消费者就可以拉取到这条消息了。

2 TCC 模式

从上面的讲解可以看到,消息队列的事务消息使用的是两阶段提交的方式。那跟 TCC 模式的两阶段提交有什么区别呢?这节我们来看一下 TCC 模式。

2.1 TCC 概述

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

TCC 模式有三个角色,TM、RM 和 TC:

以购物场景中保存订单、扣减库存、扣减金额的例子来讲,try 阶段如下图:

图片

commit/rollback 阶段如下图:

图片

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

3 总结

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


来源:君哥聊技术内容投诉

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

软考中级精品资料免费领

  • 历年真题答案解析
  • 备考技巧名师总结
  • 高频考点精准押题
  • 2024年上半年信息系统项目管理师第二批次真题及答案解析(完整版)

    难度     813人已做
    查看
  • 【考后总结】2024年5月26日信息系统项目管理师第2批次考情分析

    难度     354人已做
    查看
  • 【考后总结】2024年5月25日信息系统项目管理师第1批次考情分析

    难度     318人已做
    查看
  • 2024年上半年软考高项第一、二批次真题考点汇总(完整版)

    难度     435人已做
    查看
  • 2024年上半年系统架构设计师考试综合知识真题

    难度     224人已做
    查看

相关文章

发现更多好内容

猜你喜欢

AI推送时光机
位置:首页-资讯-后端开发
咦!没有更多了?去看看其它编程学习网 内容吧
首页课程
资料下载
问答资讯