vr彩票官网网址

0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

聊一聊消息队列技术选型的7种消息场景

芋道源码 来源:君哥聊技术 2023-12-09 17:50 次阅读

1 普通消息

消息队列最基础的功能就是生产者发送消息、Broker 保存消息,消费者来消费消息,以此实现系统解耦、削峰填谷的作用。

d8f47a96-9640-11ee-8b88-92fbcf53809c.png

普通消息是消息队列必备的消息类型,也是系统使用场景最多的一种消息。

2 顺序消息

顺序消息是指生产者发送消息的顺序和消费者消费消息的顺序是一致的。比如在一个电商场景,同一个用户提交订单、订单支付、订单出库,这三个消息消费者需要按照顺序来进行消费。如下图:

d91a241c-9640-11ee-8b88-92fbcf53809c.png

顺序消息的实现并不容易,原因如下:

生产者集群中,有多个生产者发送消息,网络延迟不一样,很难保证发送到 Broker 的消息落盘顺序是一致的;

如果 Broker 有多个分区或队列,生产者发送的消息会进入多个分区,也无法保证顺序消费;

如果有多个消费者来异步消费同一个分区,很难保证消费顺序跟生产者发送顺序一致。

要保证消息有序,需要满足两个条件:

同一个生产者必须同步发送消息到同一个分区;

一个分区只能给同一个消费者消费。

如下图:

d931cdb0-9640-11ee-8b88-92fbcf53809c.png

上面第二个条件是比较容易实现的,一个分区绑定一个消费者就可以,主要是第一个条件。

在主流消息队列的实现中,Kafka 和 Pulsar 的实现方式类似,生产者给消息赋值一个 key,对 key 做 Hash 运算来指定消息发送到哪一个分区。比如上面电商的例子,对同一个用户的一笔订单,提交订单、订单支付、订单出库这三个消息赋值同一个 key,就可以把这三条消息发送到同一个分区。

对于 RocketMQ,生产者在发送消息的时候,可以通过 MessageQueueSelector 指定把消息投递到那个 MessageQueue,如下图:

d94b1964-9640-11ee-8b88-92fbcf53809c.png

示例代码如下:

publicstaticvoidmain(String[]args)throwsUnsupportedEncodingException{
try{
DefaultMQProducerproducer=newDefaultMQProducer("please_rename_unique_group_name");
producer.start();

String[]tags=newString[]{"TagA","TagB","TagC","TagD","TagE"};
for(inti=0;i< 100; i++) {
   int orderId = i % 10;
   Message msg =
    new Message("TopicTestjjj", tags[i % tags.length], "KEY" + i,
     ("Hello RocketMQ " + i).getBytes(RemotingHelper.DEFAULT_CHARSET));
   SendResult sendResult = producer.send(msg, new MessageQueueSelector() {
    @Override
    public MessageQueue select(Listmqs,Messagemsg,Objectarg){
Integerid=(Integer)arg;
intindex=id%mqs.size();
returnmqs.get(index);
}
},orderId);

System.out.printf("%s%n",sendResult);
}

producer.shutdown();
}catch(MQClientException|RemotingException|MQBrokerException|InterruptedExceptione){
e.printStackTrace();
}
}

RabbitMQ 的实现是 Exchange 根据设置好的 Route Key 将数据路由到不同的 Queue 中。示例代码如下:

@Resource
privateAmqpTemplaterabbitTemplate;

publicvoidsend1(Stringmessage){
rabbitTemplate.convertAndSend("testExchange","testRoutingKey",message);
}

3 延时消息

或者也叫定时消息,是指消息发送后不会立即被消费,而是指定一个时间,到时间后再消费。经典的场景比如电商购物时,30 分钟未支付订单,让订单自动失效。

3.1 RocketMQ 实现

RocketMQ 定义了 18 个延时级别,每个延时级别对应一个延时时间。下面如果延迟级别是 3,则消息会延迟 10s 才会拉取。

//MessageStoreConfig类
privateStringmessageDelayLevel="1s5s10s30s1m2m3m4m5m6m7m8m9m10m20m30m1h2h";

RocketMQ 的延时消息如下图:

d95d1470-9640-11ee-8b88-92fbcf53809c.png

生产者把消费发送到 Broker 后,Broker 首先把消息保存到 SCHEDULE_TOPIC_XXXX 这个 Topic,然后调度任务会判断是否到期,如果到期,会把消息从 SCHEDULE_TOPIC_XXXX 取出投递到原始的 queue,这样消费者就可以消费到了。

RocketMQ 的延时消息只支持最大两个小时的延时,不过 RocketMQ5.0 基于时间轮算法实现了定时消息,解决了这个问题。

3.2 Pulsar 实现

Pulsar 的实现如下图:

d96f90aa-9640-11ee-8b88-92fbcf53809c.png

Pulsar 的延时消息首先会写入一个 Delayed Message Tracker 的数据结构中,Delayed Message Tracker 根据延时时间构建 delayed index 优先级队列。消费者拉取消息时,首先去 Delayed Message Tracker 检查是否有到期的消息。如果有则直接拉取进行消费。

3.3 RabbitMQ 实现

RabbitMQ 的实现方式有两种,一种是投递到普通队列都不消费,等消息过期后被投递到死信队列,消费者消费死信队列。如下图:

d97ff652-9640-11ee-8b88-92fbcf53809c.png

第二种方式是生产者发送消息时,先发送到本地 Mnesia 数据库,消息到期后定时器再将消息投递到 broker。

3.4 Kafka 实现

Kafka 本身并没有延时队列,不过可以通过生产者拦截器来实现消息延时发送,也可以定义延时 Topic,利用类似 RocketMQ 的方案来实现延时消息。

4 事务消息

事务消息是指生产消息和消费消息满足事务的特性。

RabbitMQ 和 Kafka 的事务消息都是只支持生产消息的事务特性,即一批消息要不全部发送成功,要不全部发送失败。

RabbitMQ 通过 Channel 来开启事务消息,代码如下:

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

Kafka 可以给多个生产者设置同一个事务 ID ,从而把多个 Topic 、多个 Partition 放在一个事务中,实现原子性写入。

Pulsar 的事务消息对于事务语义的定义是:允许事件流应用将消费、处理、生产消息整个过程定义为一个原子操作。可见,Pulsar 的事务消息可以覆盖消息流整个过程。

RocketMQ 的事务消息是通过 half 消息来实现的。以电商购物场景来看,账户服务扣减账户金额后,发送消息给 Broker,库存服务来消费这条消息进行扣减库存。如下图:

d9957c3e-9640-11ee-8b88-92fbcf53809c.png

可见,RocketMQ 只能保证生产者发送消息和本地事务的原子性,并不能保证消费消息的原子性。

5 轨迹消息

轨迹消息主要用于跟踪消息的生命周期,当消息丢失时可以很方便地找出原因。

轨迹消息也跟普通消息一样,也需要存储和查询,也会占用消息队列的资源,所以选择轨迹消息要考虑下面几点:

消息生命周期的关键节点一定要记录;

不能影响正常消息的发送和消费性能;

不能影响 Broker 的消息存储性能;

要考虑消息查询维度和性能。

RabbitMQ Broker 实现了轨迹消息的功能,打开 Trace 开关,就可以把轨迹消息发送到 amq.rabbitmq.trace 这个 exchange,但是要考虑轨迹消息会不会给 Broker 造成 压力进而导致消息积压。RabbitMQ 的生产者和消费者都没有实现轨迹消息,需要开发者自己来实现。

RocketMQ 生产者、Broker 和消费者都实现了轨迹消息,不过默认是关闭的,需要手工开启。

使用轨迹消息,需要考虑记录哪些节点、存储介质、性能、查询方式等问题。

6 死信队列

在消息队列中,死信队列主要应对一些异常的情况,如下图:

d9a7ce48-9640-11ee-8b88-92fbcf53809c.png

RocketMQ 实现了消费端的死信队列,当消费者消费失败时,会进行重试,如果重试 16 次还是失败,则这条消息会被发送到死信队列。

RabbitMQ 实现了生产者和 Broker 的死信队列,下面三种情况,消息会被发送到死信队列:

生产者发送消息被拒绝,并且 requeue 参数设置为 false;

Broker 消息过期了;

队列达到最大长度。

RabbitMQ 消息变成死信消息后,会被发送到死信交换机(Dead-Letter-Exchange)。

7 优先级消息

有一些业务场景下,我们需要优先处理一些消息,比如银行里面的金卡客户、银卡客户优先级高于普通客户,他们的业务需要优先处理。如下图:

d9ba8416-9640-11ee-8b88-92fbcf53809c.png

主流消息队列中,RabbitMQ 是支持优先级队列的,代码如下:

ConnectionFactoryfactory=newConnectionFactory();
connection=factory.newConnection();
Channelchannel=connection.createChannel();
Mapargs=newHashMap();
//设置优先级为5
args.put("x-max-priority",5);
channel.queueDeclare("my-priority-queue",true,false,false,args);

8 总结

消息队列技术选型,要考虑的因素很多,本文主要从业务场景来分析需要考虑的因素,同时技术上也需要考虑运维复杂度、业务规模、社区活跃度、学习成本等因素。希望本文对你使用消息队列有所帮助。






审核编辑:刘清

声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • Hash算法
    +关注

    关注

    0

    文章

    42

    浏览量

    7347
  • 调度器
    +关注

    关注

    0

    文章

    83

    浏览量

    5121

原文标题:消息队列技术选型的 7 种消息场景

文章出处:【微信号:芋道源码,微信公众号:芋道源码】欢迎添加关注!文章转载请注明出处。

收藏 人收藏

    评论

    相关推荐

    Altium中Fill,Polygon Pour,Plane的区别和用法

    Fill会造成短路,为什么还用它呢?来Altium中Fill,Polygon Pour,Plane的区别和用法
    发表于 04-25 06:29

    stm32的低功耗调试

    前言:物联网的大部分设备都是电池供电的,设备本身低功耗对延长设备使用至关重要,今天就实际调试总结stm32的低功耗调试。1、stm32在运行状态下的功耗上图截图自stm32l15x手册
    发表于 08-11 08:18

    7系列FPGA的供电部分

    前几篇咱们说了FPGA内部逻辑,本篇咱们再聊7系列FPGA的供电部分。首先咱们说spartan7系列,通常咱们需要使用以下电源轨:1,VCCINTFPGA内部核心电压。其不损坏FP
    发表于 11-11 09:27

    平衡小车代码的实现

    前言今天代码,只有直立功能的代码。代码总体思路给定个目标值,单片机通过IIC和mpu6050通信,得知数据后,根据角度环计算出个P
    发表于 01-14 08:29

    串口环形队列常用的几种方法

    1、串口常用的几种方式查询方式可靠性很高,要考虑下个数据包覆盖上个数据包的问题,小数据量,在10个字节以内,可以这样考虑, 很简单,很方便,很可靠。但是在数据量大的时候,程序阻
    发表于 07-21 15:17

    FPGA的片内资源相关知识

    大家好,到了每日学习的时间了。今天我们来FPGA的片内资源相关知识。 主流的FPGA仍是基于查找表技术的,已经远远超出了先前版本的基本性能,并且整合了常用功能(如RAM、DCM和
    的头像 发表于 05-25 14:11 8420次阅读
    <b class='flag-5'>聊</b><b class='flag-5'>一</b><b class='flag-5'>聊</b>FPGA的片内资源相关知识

    IIC总线设计

    大家好,又到了每日学习的时间了,今天咱们来 IIC 总线设计。 、概述: IIC 是Inter-Integrated Circuit的缩写,发音为eye-squared cee
    的头像 发表于 06-22 10:32 8901次阅读

    海信推出社交电视 可实现边看边、边边玩

    4月15日,海信推出了款搭载了伸缩式摄像头,同时满足6路视频通话,可实现边看边、边边玩的全新社交电视产品——社交电视S7,将于近期上市。
    发表于 04-17 09:19 2014次阅读

    FPGA中的彩色转灰度的算法

    大家好,又到了每日学习的时间了,今天我们来FPGA学习中可以遇到的些算法,今天就
    的头像 发表于 04-15 15:47 1596次阅读

    【职场杂谈】与嵌入式物联网架构师几个话题

    【职场杂谈】与嵌入式物联网架构师几个话题
    的头像 发表于 08-23 09:19 882次阅读
    【职场杂谈】与嵌入式物联网架构师<b class='flag-5'>聊</b><b class='flag-5'>一</b><b class='flag-5'>聊</b>几个话题

    华为云弹性公网IP的那些事儿

    华为云弹性公网IP的那些事儿 如今,企业上云已成为热门话题,云可以驱动流程创新和业务创新,成为企业新的利润增长点,被看成是企业实现数字化转型的必经之路。弹性公网IP作为一种网络基
    的头像 发表于 11-21 15:20 547次阅读
    <b class='flag-5'>聊</b><b class='flag-5'>一</b><b class='flag-5'>聊</b>华为云弹性公网IP的那些事儿

    从焊接角度,设计PCB的5个建议

    完成个电路板,需要PCB工程师、焊接工艺、焊接工人等诸多环节的把控。今天通过定位孔、MARK点、留边、焊盘过孔、辅助工具这五个方面从画板的角度跟大家PCB设计。
    的头像 发表于 02-06 10:31 1469次阅读
    从焊接角度<b class='flag-5'>聊</b><b class='flag-5'>一</b><b class='flag-5'>聊</b>,设计PCB的5个建议

    LDO的选型和应用

    在实际应用过程中,因为涉及到转换效率问题, 输出电流的大小和输入输出电压都有定的关系。换句话说,达到最大的输出电流,需要满足定的条件。 在选型时,要考虑留有些余量,如电路最
    发表于 09-11 10:55 109次阅读
    <b class='flag-5'>聊</b><b class='flag-5'>一</b><b class='flag-5'>聊</b>LDO的<b class='flag-5'>选型</b>和应用

    简单DPT技术-double pattern technology

    今天想来简单DPT技术-double pattern technology,也就是双层掩模版技术,在目前先进工艺下,这项
    的头像 发表于 12-05 14:26 76次阅读

    芯片设计的NDR是什么?

    今天突然想route相关的问题,讲讲NDR是什么,我也梳理总结下我对NDR的认识。
    的头像 发表于 12-06 15:14 107次阅读