最全RocketMQ学习资料

本文深入探讨了RocketMQ,一种广泛应用于分布式系统的消息中间件。RocketMQ提供消息模型、基础概念,包括消息生产者、消费者、主题、代理服务器、名字服务等。此外,还详细介绍了RocketMQ的消息类型、特性、设计与实现,如顺序消息、事务消息、消息过滤、流量控制和死信队列等,展示了RocketMQ在消息可靠性、性能优化等方面的优秀特性。
摘要由CSDN通过智能技术生成

1、MQ介绍

1.1 什么是MQ?为什么要用MQ?

MQ就是MessageQueue,消息队列

MQ的应用场景主要有以下几个方面:

  • 异步解耦

交易系统作为淘宝和天猫主站最核心的系统,每笔交易订单数据的产生会引起几百个下游业务系统的关注,包括物流、购物车、积分、流计算分析等等,整体业务系统庞大而且复杂,消息队列RocketMQ可实现异步通信和应用解耦,确保主站业务的连续性。

  • 削峰填谷

诸如秒杀、抢红包、企业开门红等大型活动时皆会带来较高的流量脉冲,或因没做相应的保护而导致系统超负荷甚至崩溃,或因限制太过导致请求大量失败而影响用户体验,消息队列RocketMQ版可提供削峰填谷的服务来解决该问题。

  • 顺序收发

例如证券交易过程时间优先原则,交易系统中的订单创建、支付、退款等流程,航班中的旅客登机消息处理等等。

  • 分布式事务一致性

交易系统、支付红包等场景需要确保数据的最终一致性,使用RocketMQ 既可以实现系统之间的解耦,又可以保证最终的数据一致性。

1.2 各类MQ的对比

kafka主要定位于日志传输,对于使用在淘宝交易、订单、充值等场景下还有诸多特性不满足

rocketmq 相比kafka 更加关注消息的可靠性,支持消息重试,死信队列

2、RocketMQ

当前最新的版本是4.7.1,详细可见官网

​RocketMQ的官网地址:http://rocketmq.apache.org

github地址是:https://github.com/apache/rocketmq

中文文档:https://github.com/apache/rocketmq/tree/master/docs/cn

Issues: https://github.com/apache/rocketmq/issues

admin控制台:https://github.com/apache/rocketmq-externals

aliyun文档:https://help.aliyun.com/document_detail/29532.html?spm=a2c4g.11186623.6.548.7e901a52Psiodk

2.1 RocketMQ 基础概念

1 消息模型(Message Model)

RocketMQ主要由 Producer、Broker、Consumer 三部分组成,其中Producer 负责生产消息,Consumer 负责消费消息,Broker 负责存储消息。Broker 在实际部署过程中对应一台服务器,每个 Broker 可以存储多个Topic的消息,每个Topic的消息也可以分片存储于不同的 Broker。Message Queue 用于存储消息的物理地址,每个Topic中的消息地址存储于多个 Message Queue 中。ConsumerGroup 由多个Consumer 实例构成。

2 消息生产者(Producer)

负责生产消息,一般由业务系统负责生产消息。一个消息生产者会把业务应用系统里产生的消息发送到broker服务器。RocketMQ提供多种发送方式,同步发送、异步发送、顺序发送、单向发送。同步和异步方式均需要Broker返回确认信息,单向发送不需要。

3 消息消费者(Consumer)

负责消费消息,一般是后台系统负责异步消费。一个消息消费者会从Broker服务器拉取消息、并将其提供给应用程序。从用户应用的角度而言提供了两种消费形式:拉取式消费、推动式消费。

4 主题(Topic)

表示一类消息的集合,每个主题包含若干条消息,每条消息只能属于一个主题,是RocketMQ进行消息订阅的基本单位。

5 代理服务器(Broker Server)

消息中转角色,负责存储消息、转发消息。代理服务器在RocketMQ系统中负责接收从生产者发送来的消息并存储、同时为消费者的拉取请求作准备。代理服务器也存储消息相关的元数据,包括消费者组、消费进度偏移和主题和队列消息等。

6 名字服务(Name Server)

名称服务充当路由消息的提供者。生产者或消费者能够通过名字服务查找各主题相应的Broker IP列表。多个Nameserver实例组成集群,但相互独立,没有信息交换。

7 拉取式消费(Pull Consumer)

Consumer消费的一种类型,应用通常主动调用Consumer的拉消息方法从Broker服务器拉消息、主动权由应用控制。一旦获取了批量消息,应用就会启动消费过程。

8 推动式消费(Push Consumer)

Consumer消费的一种类型,该模式下Broker收到数据后会主动推送给消费端,该消费模式一般实时性较高。

9 生产者组(Producer Group)

同一类Producer的集合,这类Producer发送同一类消息且发送逻辑一致。如果发送的是事务消息且原始生产者在发送之后崩溃,则Broker服务器会联系同一生产者组的其他生产者实例以提交或回溯消费。

10 消费者组(Consumer Group)

同一类Consumer的集合,这类Consumer通常消费同一类消息且消费逻辑一致。消费者组使得在消息消费方面,实现负载均衡和容错的目标变得非常容易。要注意的是,消费者组的消费者实例必须订阅完全相同的Topic。RocketMQ 支持两种消息模式:集群消费(Clustering)和广播消费(Broadcasting)。

11 集群消费(Clustering)

集群消费模式下,相同Consumer Group的每个Consumer实例平均分摊消息。

12 广播消费(Broadcasting)

广播消费模式下,相同Consumer Group的每个Consumer实例都接收全量的消息。

13 普通顺序消息(Normal Ordered Message)

普通顺序消费模式下,消费者通过同一个消费队列收到的消息是有顺序的,不同消息队列收到的消息则可能是无顺序的。

14 严格顺序消息(Strictly Ordered Message)

严格顺序消息模式下,消费者收到的所有消息均是有顺序的。

15 消息(Message)

消息系统所传输信息的物理载体,生产和消费数据的最小单位,每条消息必须属于一个主题。RocketMQ中每个消息拥有唯一的Message ID,且可以携带具有业务标识的Key。系统提供了通过Message ID和Key查询消息的功能。

16 标签(Tag)

为消息设置的标志,用于同一主题下区分不同类型的消息。来自同一业务单元的消息,可以根据不同业务目的在同一主题下设置不同标签。标签能够有效地保持代码的清晰度和连贯性,并优化RocketMQ提供的查询系统。消费者可以根据Tag实现对不同子主题的不同消费逻辑,实现更好的扩展性。

2.2 RocketMQ 消息类型

样例代码:https://github.com/apache/rocketmq/tree/master/example/src/main

普通消息

普通消息分为三种同步发送、异步发送以及单向发送。

1、同步发送消息的样例见:org.apache.rocketmq.example.simple.Producer,等待消息返回后再继续进行下面的操作。

2、异步发送消息的样例见:org.apache.rocketmq.example.simple.AsyncProducer

3、单向发送消息的样例:

public class OnewayProducer {
    public static void main(String[] args) throws Exception{
        //Instantiate with a producer group name.
        DefaultMQProducer producer = new           DefaultMQProducer("please_rename_unique_group_name");
        // Specify name server addresses.
        producer.setNamesrvAddr("localhost:9876");
        //Launch the instance.
        producer.start();
        for (int i = 0; i < 100; i++) {
            //Create a message instance, specifying topic, tag and message body.
            Message msg = new Message("TopicTest" /* Topic */,
                "TagA" /* Tag */,
                ("Hello RocketMQ " +
                    i).getBytes(RemotingHelper.DEFAULT_CHARSET) /* Message body */
            );
            //Call send message to deliver message to one of brokers.
            producer.sendOneway(msg);
        }
        //Wait for sending to complete
        Thread.sleep(5000);        
        producer.shutdown();
    }
}

producer.sendOneWay方式来发送消息,这个方法没有返回值,也没有回调。就是只管把消息发出去就行了。

​ 4、使用消费者消费消息。

​ 消费者消费消息有两种模式,一种是拉模式,另一种是推模式。

​ 拉模式的样例见:org.apache.rocketmq.example.simple.PullConsumer

public class PullConsumer {
    private static final Map<MessageQueue, Long> OFFSE_TABLE = new HashMap<MessageQueue, Long>();

    public static void main(String[] args) throws MQClientException {
        DefaultMQPullConsumer consumer = new DefaultMQPullConsumer("please_rename_unique_group_name_5");
        consumer.setNamesrvAddr("127.0.0.1:9876");
        consumer.start();

        Set<MessageQueue> mqs = consumer.fetchSubscribeMessageQueues("broker-a");
        for (MessageQueue mq : mqs) {
            System.out.printf("Consume from the queue: %s%n", mq);
            SINGLE_MQ:
            while (true) {
                try {
                    PullResult pullResult =
                            consumer.pullBlockIfNotFound(mq, null, getMessageQueueOffset(mq), 32);
                    System.out.printf("%s%n", pullResult);
                    putMessageQueueOffset(mq, pullResult.getNextBeginOffset());
                    switch (pullResult.getPullStatus()) {
                        case FOUND:
                            break;
                        case NO_MATCHED_MSG:
                            break;
                        case NO_NEW_MSG:
                            break SINGLE_MQ;
                        case OFFSET_ILLEGAL:
                            break;
                        default:
                            break;
                    }
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        }

        consumer.shutdown();
    }

    private static long getMessageQueueOffset(MessageQueue mq) {
        Long offset = OFFSE_TABLE.get(mq);
        if (offset != null)
            return offset;

        return 0;
    }

    private static void putMessageQueueOffset(MessageQueue mq, long offset) {
        OFFSE_TABLE.put(mq, offset);
    }

}

​ 推模式的样例见:org.apache.rocketmq.example.simple.PushConsumer

public class PushConsumer {

    public static void main(String[] args) throws InterruptedException, MQClientException {
        DefaultMQPushConsumer consumer = new DefaultMQPushConsumer("CID_JODIE_1");
        consumer.subscribe("TopicTest", "*");
        consumer.setConsumeFromWhere(ConsumeFromWhere.CONSUME_FROM_FIRST_OFFSET);
        //wrong time format 2017_0422_221800
        consumer.setConsumeTimestamp("20181109221800");
        consumer.registerMessageListener(new MessageListenerConcurrently() {

            @Override
            public ConsumeConcurrentlyStatus consumeMessage(List<MessageExt> msgs, ConsumeConcurrentlyContext context) {
                System.out.printf("%s Receive New Messages: %s %n", Thread.currentThread().getName(), msgs);
                return ConsumeConcurrentlyStatus.CONSUME_SUCCESS;
            }
        });
        consumer.start();
        System.out.printf("Consumer Started.%n");
    }
}

实际上RocketMQ的推模式也是由拉模式封装出来的。

采用Pull方式,如何设置Pull消息的拉取频率需要重点去考虑,举个例子来说,可能1分钟内连续来了1000条消息,然后2小时内没有新消息产生(概括起来说就是“消息延迟与忙等待”)。如果每次Pull的时间间隔比较久,会增加消息的延迟,即消息到达消费者的时间加长,MQ中消息的堆积量变大;若每次Pull的时间间隔较短,但是在一段时间内MQ中并没有任何消息可以消费,那么会产生很多无效的Pull请求的RPC开销,影响MQ整体的网络性能;

采用Push方式,可以尽可能实时地将消息发送给消费者进行消费。但是,在消费者的处理消息的能力较弱的时候(比如,消费者端的业务系统处理一条消息的流程比较复杂,其中的调用链路比较多导致消费时间比较久。概括起来地说就是“慢消费问题”),而MQ不断地向消费者Push消息,消费者端的缓冲区可能会溢出,导致异常;

pull模式还有一种方式

public class PullScheduleService {

    public static void main(String[] args) throws MQClientException {
        final MQPullConsumerScheduleService scheduleService = new MQPullConsumerScheduleService("GroupName1");

        scheduleService.setMessageModel(MessageModel.CLUSTERING);
        scheduleService.registerPullTaskCallback("TopicTest", new PullTaskCallback() {

            @Override
            public void doPullTask(MessageQueue mq, PullTaskContext context) {
                MQPullConsumer consumer = context.getPullConsumer();
                try {

                    long offset = consumer.fetchConsumeOffset(mq, false);
                    if (offset < 0)
                        offset = 0;

                    PullResult pullResult = consumer.pull(mq, "*", offset, 32);
                    System.out.printf("%s%n", offset + "\t" + mq + "\t" + pullResult);
                    switch (pul
  • 2
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
RocketMQ是一个开源的分布式消息队列系统,具有高可靠性、高吞吐量、低延迟等特点,适用于大规模分布式系统的消息处理。本文将简单介绍RocketMQ的基本概念、架构和使用方式。 一、基本概念 1. 消息:消息是RocketMQ传递的基本单位,它包含了消息主题、消息内容等信息。 2. 生产者:生产者是RocketMQ消息的发送方,它将消息发送到指定的主题。 3. 消费者:消费者是RocketMQ消息的接收方,它从指定的主题中获取消息并进行处理。 4. 主题:主题是RocketMQ中消息的分类,类似于队列的概念,生产者将消息发送到指定的主题,消费者从指定的主题中获取消息。 5. 队列:主题下面可以有多个队列,一个队列对应一个消费者。消息会被均匀地分配到各个队列中,以实现负载均衡。 6. Broker:Broker是RocketMQ的核心组件,负责存储消息和处理消息的发送和接收。 二、架构 RocketMQ的架构主要分为三个层次:生产者、Broker和消费者。 1. 生产者:生产者将消息发送到主题,主题下面可以有多个队列。生产者可以通过集群方式实现高可用性,即多个生产者组成一个生产者组,将消息同时发送到多个Broker上。 2. Broker:Broker是RocketMQ的核心组件,负责存储消息和处理消息的发送和接收。一个Broker可以管理多个主题,每个主题下面可以有多个队列。Broker可以通过集群方式实现高可用性,即多个Broker组成一个Broker集群,通过主从复制方式实现数据的同步。 3. 消费者:消费者从指定的主题中获取消息并进行处理。消费者可以通过集群方式实现高可用性,即多个消费者组成一个消费者组,从多个Broker上同时获取消息。 三、使用方式 1. 下载安装:从RocketMQ官网下载安装包,并解压到指定目录。然后启动Name Server和Broker服务。 2. 创建主题:使用RocketMQ提供的命令行工具创建主题。 3. 发送消息:使用RocketMQ提供的Java API创建生产者,然后发送消息到指定的主题。 4. 接收消息:使用RocketMQ提供的Java API创建消费者,从指定的主题中获取消息并进行处理。 以上是RocketMQ的基本概念、架构和使用方式的简单介绍。如果需要深入学习RocketMQ的更多内容,可以查阅官方文档或者参考开源社区的相关资料。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

行走在江湖

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值