★消息队列16篇

1 认识RocketMQ

RocketMQ是一款基于Java开发的分布式消息中间件,它以其高性能、高可靠性、高实时性以及分布式特性而广受好评。

它支持事务消息、顺序消息、批量消息、定时消息、消息回溯等。互联网场景中经常使用RocketMQ进行消息路由、订阅发布、异步解耦、流量削减峰等操作,来缓解系统的压力。

2 三种常见的消息中间件比较

特性 RabbitMQ RocketMQ Kafka
开发语言 erlang java scala
单机吞吐量 1w+ 10w+ 10w+
时效性 us级 ms级 ms级以内
可用性 高(主从架构) 非常高(分布式架构) 非常高(分布式架构)
消息可靠性 基本不丢 参数化配置和持久化:基本不丢 参数化配置和持久化:基本不丢
功能特性 基于erlang开发,所以并发能力很强,性能极其好,延时很低;管理界面较丰富 MQ功能比较完备,扩展性佳 只支持主要的MQ功能,像一些消息查询,消息回溯等功能没有提供,毕竟是为大数据准备的,在大数据领域应用广。
生态 开源、稳定、社区活跃度高 阿里开源,交给Apache,社区活跃度低 Apache开发,开源、高吞吐量、社区活跃度高

技术选型决策参考:

(1)中小型软件,建议选RabbitMQ, 中小型软件数据量没那么大,选消息中间件,应首选功能比较完备的,所以kafka排除。

不考虑rocketmq的原因是,rocketmq是阿里出品,如果阿里放弃维护rocketmq,中小型公司一般抽不出人来进行rocketmq的定制化开发,因此不推荐。

(2)大型软件公司,根据具体使用在rocketMq和kafka之间二选一。一方面,大型软件公司,具备足够的资金搭建分布式环境,也具备足够大的数据量。

针对rocketMQ,大型软件公司也可以抽出人手对rocketMQ进行定制化开发,毕竟有能力改JAVA源码的人,还是相当多的。

至于kafka,根据业务场景选择,如果有日志采集功能,肯定是首选kafka了。具体该选哪个,看使用场景。引入MQ之后,必然导致系统可用性降低,复杂性增大。

3 消息中间件使用场景

1. 解耦: 比如说系统A会交给系统B去处理一些事情,但是A不想直接跟B有关联,避免耦合太强,就可以通过在A,B中间加入消息队列,A将要任务的事情交给消息队列 ,B订阅消息队列来执行任务。

这种场景很常见,比如A是订单系统,B是库存系统,可以通过消息队列把削减库存的工作交予B系统去处理。如果A系统同时想让B、C、D...多个系统处理问题的时候,这种优势就更加明显了。

2. 有序性: 先进先出原理,先来先处理,比如一个系统处理某件事需要很长一段时间,但是在处理这件事情时候,有其他人也发出了请求,可以把请求放在消息队里,一个一个来处理。

对数据的顺序性和一致性有强需求的业务,比如同一张银行卡同时被多个入口使用,需要保证入账出账的顺序性,避免出现数据不一致。

3. 消息路由/数据分发: 按照不同的规则,将队列中消息发送到不同的其他队列中

通过消息队列将不同染色的请求发送到不同的服务去操作。这样达成了流量按照业务拆分的目的。

4、异步处理: 处理一项任务的时候,有3个步骤A、B、C,需要先完成A操作, 然后做B、C 操作。任务执行成功与否强依赖A的结果,但不依赖B、C 的结果。

如果我们使用串行的执行方式,那处理任务的周期就会变长,系统的整体吞吐能力也会降低(在同一个系统中做异步其实也是比较大的开销),所以使用消息队列是比较好的办法。

登录操作就是典型的场景:A:执行登录并得到结果、B:记录登录日志、C:将用户信息和Token写入缓存。 执行完A就可以从登录页跳到首页了,B、C让服务慢慢去消化,不阻塞当前操作。

5、削峰: 将峰值期间的操作削减,比如A同学的整个操作流程包含12个步骤,后续的11个步骤是不需要强关注结果的数据,可以放在消息队列中。

4 MQ的概念、结构和原理

4.1 构成说明

RocketMQ主要有四大核心组成部分:NameServer、Broker、Producer以及Consumer四部分。这些角色通常以集群的方式存在,RocketMQ 基于纯Java开发,具有高吞吐量、高可用性、适合大规模分布式系统应用的特点。

  • RockerMQ想要启动,首先需要启动 NameServer,再启动 Brober 主机
  • Broker 会向 NameServer 注册对应的路由和服务
  • Producer会进行路的发现,向NameServer请求Broker路由信息,进行消息的发送
  • Consumer要连通NameServer,获取到相关的路由信息,方便我们进行消息的订阅
  • Broker 主要负责消息的存储,不管是生产消息还是订阅消息,消息的来源都是 Broker,
  • 消息的发送(Producer)只会发到主节点,然后Broker会进行消息的同步,同步到从节点,作为消费者(Consumer)也只会优先从Master节点,获取消息,进行消费
  • Broker主节点不可用或者非常繁忙,会选择从节点进行消费

1. Producer:

负责生产消息,一般由业务系统负责。生产者通过调用API将消息发送到指定的Topic(主题)中。

2. Broker:

消息存储中心,负责接收来自Producer的消息并存储,同时Consumer也从这里取得消息。Broker还存储与消息相关的元数据,包括消费者组、消费进度偏移量、队列信息等。每个Broker可以存储多个Topic的消息,每个Topic的消息也可以分片存储于不同的Broker。在实际部署中,Broker对应一台服务器,并分为Master与Slave两种类型,Master负责读写,Slave只负责读,以此实现数据的备份和负载均衡。

3. Consumer:

负责消费消息,一般由后台系统负责。消费者通过订阅Topic来获取消息,并根据业务逻辑进行处理。消费者可以以集群消费或广播消费的方式消费消息。

4. NameServer:

充当路由消息的提供者,负责保存Broker的元数据信息,并供Producer和Consumer查询。NameServer被设计成几乎无状态的,可以横向扩展,节点之间无通信。

4.2 基础概念

4.2.1 Group(分组)

在RocketMQ中,Group功能是其核心特性之一。Group主要分为发送端Group和消费端Group。

  • 发送端Group:允许将多个发送者(Producer)组织成一个发送者组。通过发送端Group,可以实现对消息的批量处理和负载均衡,提高系统性能和可靠性。
  • 消费端Group:RocketMQ允许消费者同时订阅多个主题(Topic),这些消费者可以被组织成一个或多个消费组。消费组内的消费者可以共同分担消息的消费任务,实现负载均衡和容错。当某个消费者出现故障时,其他消费者可以接管其消费任务,确保消息被及时处理。同时,消费组还支持消息过滤和顺序消费等高级特性。

4.2.2 Topic(主题)

用来区分消息的种类,表示一类消息的逻辑名字,消息的逻辑管理单位,无论生产还是消费消息,都需要执行Topic。比如一个Topic专门用于用户订单消息发送,一个Topic专门用于扣减或增加积分的。

  • 一个发送者可以发送消息给一个或者多个Topic
  • 一个消息接受者可以订阅一个或多个Topic消息

4.2.3 Message Queue(消息队列)

MessageQueue是RocketMQ中用于存储和传输消息的数据结构。每个MessageQueue都有一个唯一标识符,由Topic名称和队列编号组成。MessageQueue具有以下特点:

  • 唯一标识:确保每个MessageQueue都可以被唯一地识别和定位。
  • 消息顺序性:对于同一个MessageQueue中的消息,RocketMQ保证其消费的顺序性,即先进先出(FIFO)。
  • 负载均衡:RocketMQ通过动态调整消息分配策略,将消息均匀地分布到所有的MessageQueue中,实现负载均衡,避免某个MessageQueue过载而其他MessageQueue空闲的情况。
  • 高可用性:RocketMQ支持将多个Broker节点组成集群,每个MessageQueue可以在不同的Broker节点上进行主从复制,提供高可用性和数据冗余。即使某个Broker节点出现故障,其他节点也可以继续提供服务,确保消息的可靠传输。

4.2.4 Tag(标签)

Tag是RocketMQ中用于对消息进行分类和过滤的标记。生产者可以在发送消息时指定Tag,消费者可以根据Tag来过滤和订阅消息。Tag的使用可以使得消息的管理和消费更加灵活和高效。例如,一个电商系统可能会根据商品的类别(如服装、电子产品等)来设置不同的Tag,消费者可以根据这些Tag来订阅和处理特定类别的消息。

4.2.5 Offset(偏移量)

Offset在RocketMQ中用于标识消费者在消息队列中的位置。每个消费者都会维护一个Offset,以便知道下一次从哪里开始消费。Offset的使用可以确保消息不丢失、避免消息重复消费以及支持消息的顺序消费。

  • Message queue 是无限长的数组。一条消息进来下标就会涨 1,而这个数组的下标就是 offset。
  • 确保消息不丢失:通过持久化Offset,即使在消费者宕机后重启,也能从上次消费的位置继续消费,保证消息至少被消费一次。
  • 避免消息重复消费:消费者在成功处理消息后更新Offset,确保每条消息只被消费一次。
  • 支持消息顺序消费:对于顺序消息,通过维护Offset可以保证消息的顺序消费。

5 程序实现

5.1 Java中引入和实现RocketMQ

  1. 引入依赖

    在Java项目中,通常通过Maven或Gradle等构建工具来引入RocketMQ的客户端依赖。以Maven为例,可以在pom.xml文件中添加以下依赖:

    <dependency>
    <groupId>org.apache.rocketmq</groupId>
    <artifactId>rocketmq-client</artifactId>
    <version>最新版本号(5.3.1)</version>
    </dependency>
  2. 实现生产者

    在Java中,通过创建DefaultMQProducer对象来实现消息的生产者。生产者需要设置NameServer地址,并调用start()方法初始化。然后,可以创建Message对象并设置主题、标签和消息内容,最后调用send()方法发送消息。


    public class Producer {
    public static void main(String[] args) throws Exception {
    // 创建一个消息生产者,并设置消息生产者组
    DefaultMQProducer producer = new DefaultMQProducer("your_producer_group");
    // 指定NameServer地址
    producer.setNamesrvAddr("your_nameserver_address");
    // 初始化Producer
    producer.start(); // 创建消息对象,并设置主题、标签和消息内容
    Message msg = new Message("your_topic", "your_tag", "Hello RocketMQ".getBytes());
    // 发送消息并获取发送结果
    SendResult sendResult = producer.send(msg);
    System.out.printf("%s%n", sendResult); // 关闭生产者实例
    producer.shutdown();
    }
    }
  3. 实现消费者

    在Java中,通过创建DefaultMQPushConsumer对象来实现消息的消费者。消费者需要设置NameServer地址和消费组名称,并调用subscribe()方法订阅主题和标签。然后,注册消息监听器来处理接收到的消息。


    public class Consumer {
    public static void main(String[] args) throws Exception {
    // 创建一个消息消费者,并设置消息消费者组
    DefaultMQPushConsumer consumer = new DefaultMQPushConsumer("your_consumer_group");
    // 指定NameServer地址
    consumer.setNamesrvAddr("your_nameserver_address");
    // 订阅指定Topic下的所有消息
    consumer.subscribe("your_topic", "*"); // 注册消息监听器
    consumer.registerMessageListener(new MessageListenerConcurrently() {
    @Override
    public ConsumeConcurrentlyStatus consumeMessage(List<MessageExt> msgs, ConsumeConcurrentlyContext context) {
    for (MessageExt msg : msgs) {
    System.out.printf("接收到消息: %s%n", new String(msg.getBody()));
    }
    return ConsumeConcurrentlyStatus.CONSUME_SUCCESS;
    }
    }); // 启动消费者实例
    consumer.start();
    }
    }

6 总结

本文只是了解下RocketMQ的基本原理和实现,在后面的章节中,我们会带来RocketMQ的完整解读。

RocketMQ系列1:基础介绍的更多相关文章

  1. 【01】emmet系列之基础介绍

    [01]emmet系列之基础介绍 [02]emmet系列之HTML语法 [03]emmet系列之CSS语法 [04]emmet系列之编辑器 [05]emmet系列之各种缩写 相关网址 官网:http: ...

  2. Logstash学习系列之基础介绍

    Logstash功能特性 能集中处理各种类型的数据 能标准化不同模式和格式的数据 能快速的扩展自定义日志的格式 它具有收集,分析和转发数据流的功能 Logstash运行参数 -f 指定配置文件 -e ...

  3. openresty开发系列13--lua基础语法2常用数据类型介绍

    openresty开发系列13--lua基础语法2常用数据类型介绍 一)boolean(布尔)布尔类型,可选值 true/false: Lua 中 nil 和 false 为"假" ...

  4. [转帖]《吊打面试官》系列-Redis基础

    <吊打面试官>系列-Redis基础 https://www.cnblogs.com/aobing/archive/2019/11/07/11811194.html   你知道的越多,你不知 ...

  5. 「译」JUnit 5 系列:基础入门

    原文地址:http://blog.codefx.org/libraries/junit-5-basics/ 原文日期:25, Feb, 2016 译文首发:Linesh 的博客:JUnit 5 系列: ...

  6. [WPF系列]从基础起步学习系列计划

    引言 WPF技术已经算不什么新技术,一搜一大把关于WPF基础甚至高级的内容.之前工作中一直使用winform所以一直没有深入学习WPF,这次因项目中使用了WPF技术来实现比较酷的展示界面.我在这里只是 ...

  7. WPF入门教程系列二——Application介绍

    一.Application介绍 WPF和WinForm 很相似, WPF与WinForm一样有一个 Application对象来进行一些全局的行为和操作,并且每个 Domain (应用程序域)中仅且只 ...

  8. 快速入门系列--WebAPI--01基础

    ASP.NET MVC和WebAPI已经是.NET Web部分的主流,刚开始时两个公用同一个管道,之后为了更加的轻量化(WebAPI是对WCF Restful的轻量化),WebAPI使用了新的管道,因 ...

  9. .NET 4 并行(多核)编程系列之一入门介绍

    .NET 4 并行(多核)编程系列之一入门介绍 本系列文章将会对.NET 4中的并行编程技术(也称之为多核编程技术)以及应用作全面的介绍. 本篇文章的议题如下:  1. 并行编程和多线程编程的区别.  ...

  10. (C#)Windows Shell 编程系列1 - 基础,浏览一个文件夹

    原文 (C#)Windows Shell 编程系列1 - 基础,浏览一个文件夹 (本系列文章由柠檬的(lc_mtt)原创,转载请注明出处,谢谢-) Windows Shell 编程,即 Windows ...

随机推荐

  1. 云边协同的RTC如何助力即构全球实时互动业务实践

    ​ 由 51 CTO 主办的"WOT 全球技术创新大会 2023·深圳站"于 11 月 24 日 - 25 日召开,即构科技后台技术总监肖潇以"边缘容器在全球音视频场景的 ...

  2. 26.删除有序数组中的重复项 Golang实现

    题目描述: 给你一个 非严格递增排列 的数组 nums ,请你 原地 删除重复出现的元素,使每个元素 只出现一次 ,返回删除后数组的新长度.元素的 相对顺序 应该保持 一致 .然后返回 nums 中唯 ...

  3. Spring —— bean配置

    基础配置      别名配置    作用范围配置      适合交给容器进行管理的bean   (复用性的对象,无需重复创建的对象) 表现层对象 业务层对象 数据层对象 工具对象   不适合交给容器管 ...

  4. ConcurrentLinkedQueue详解(图文并茂)

    前言 ConcurrentLinkedQueue是基于链接节点的无界线程安全队列.此队列按照FIFO(先进先出)原则对元素进行排序.队列的头部是队列中存在时间最长的元素,而队列的尾部则是最近添加的元素 ...

  5. [C++] Rander

    注 这个Rander对单个数据的平均分散不太优秀,但是获取大量数据十分平均 当前版本 2.0 for Windows 功能 int rander::reset() 按默认大小重置随机数序列,返回默认大 ...

  6. QQ或者微信可以放昵称的超好看的符号

    ☪︎⋆ ✯ ⛈ •ᴗ• •ᴥ• ◔.̮◔ ᕱ ᕱ ⸝⸝· ᴥ ·⸝⸝ ʕ·͡ˑ·ཻʔ ʕ•̫͡•ོʔ ˃̣̣̥᷄⌓˂̣̣̥᷅ °꒰'ꀾ'꒱° ⋆ᶿ̵᷄ ˒̼ ᶿ̵᷅⋆ ˙ϖ˙ ⚝ ︎ .˗ˏˋ♡ˎˊ˗ ...

  7. Nuxt.js 应用中的 app:rendered 钩子详解

    title: Nuxt.js 应用中的 app:rendered 钩子详解 date: 2024/10/2 updated: 2024/10/2 author: cmdragon excerpt: 摘 ...

  8. yarn 和 npm 不能混合使用

    当有 yarn.lock 的时候说明项目使用的yarn 创建的 则后面的都要使用 yarn 操作,比如下载 包 等 : 当项目没有 yarn.lock 而是 package.json.lock 说明项 ...

  9. apisix~kafka-logger插件

    作用 将http请求与响应的内容发到kafka的topic,以json的形式发送存储 配置相关 log_format为自定义配置字段,添加后,默认的请求响应消息将被覆盖 { "_meta&q ...

  10. Need BLUETOOTH PRIVILEGED permission以及requestMtu导致蓝牙断连问题

    在部分Android手机上,当连接上GATTService后直接requestMtu有可能会造成蓝牙连接中断,随后继续重新连接会报错Need BLUETOOTH PRIVILEGED permissi ...