Rocket学习小结

本文详述了RocketMQ的介绍、安装配置、监控界面安装、架构解析,探讨了NameServer的角色,以及Producer和Consumer的实现。重点讨论了RocketMQ如何确保消息一致性和处理重复消息的方法,同时还介绍了消息优先级和过滤机制,以及发送消息的负载均衡策略。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

一:RocketMQ简介

RocketMQ是分布式、队列模型的消息中间件, MetaQ 的 3.0 版本。
特点
数据可靠性
消费失败重试
严格的消息顺序
定时消息
消息查询
消息回溯
单机支持的队列数(5万)
支持push、pull两种方式消费消息
适用场景
应用解耦、流量削峰、异步处理、消息通讯

二:RocketMQ安装配置

  1. 安装jdk

  2. 安装RocketMQ
    下载安装包如alibaba-rocketmq3.5.8.zip

  3. Broker 集群部署方式
    进入conf目录,提供以下几种broker部署方式:
2m-noslave
2m-2s-sync
2m-2s-async
  1. 启动namesrv
nohup sh mqnamesrv &
  1. 启动broker master
nohup sh mqbroker -n 172.16.8.106:9876  -c ../conf/2m-2s-sync/broker-a.properties &
  1. 启动 broker slave
 nohup sh mqbroker -n 172.16.8.106:9876  -c ../conf/2m-2s-sync/broker-b.properties &

broker.properties文件关键配置:brokerName、brokerId、namesrvAddr、brokerRole
broker master与slave配对规则

7.关闭nameserver和所有的broker

sh mqshutdown namesrv
sh mqshutdown broker

nameserver监听9876端口,broker默认监听10911端口,启动前,先开放必要端口

三:web监控界面安装

四:RocketMQ的结构组成-多master多slave部署图

这里写图片描述

下面解读一下它们之间的关系:

  • 1.NameServer互相独立,彼此没有通信关系,单台NameServer挂掉,不影响其他NameServer。NameServer不去连接别的机器,不会主动推消息。
  • 2.单个broker(Master、Slave)与所有NameServer进行定时注册,以便告知NameServer自己还活着。Broker每隔30秒向所有NameServer发送心跳,心跳包含了自身的topic配置信息。NameServer每隔10秒,扫描所有还存活的broker连接,如果某个连接的最后更新时间与当前时间差值超过2分钟,则断开此连接。此外,NameServer也会断开此broker下所有与slave的连接。同时更新topic与队列的对应关系,但不会通知生产者和消费者。
    Broker slave 同步或者异步从Broker master 上拷贝数据。
  • 3.consumer随机与一个NameServer建立长连接,如果该NameServer断开,则从NameServer列表中查找下一个进行连接。
    consumer主要从NameServer中根据topic查询broker的地址,查到就会缓存到客户端,并向提供topic服务的master、slave建立长连接,且定时向master、slave发送心跳。如果broker宕机,则NameServer会将其剔除,而consumer端的定时任务MQClientInstance.this.updateTopicRouteInfoFromNameServer每30秒执行一次,会将topic对应的broker地址拉取下来,此地址已经为slave地址了,故此时consumer会从slave上消费。 消费者与master和slave都建有连接,在不同场景有不同的消费规则。
  • 4.Producer随机与一个NameServer建立长连接,每隔30秒(此处时间可配置)从NameServer获取topic的最新队列情况,这就表示如果某个broker
    master宕机,producer最多30秒才能感知,在这个期间,发往该broker
    master的消息将会失败。Producer会向提供topic服务的master建立长连接,且定时向master发送心跳。生产者与所有的master连接,但不能向slave写入。
    客户端是先从NameServer寻址的,得到可用Broker的IP和端口信息,然后自己去连接broker。
    (ps:我们在设计系统的时候,有一些全局使用的公用信息,可以单独独立一个模块进行专门的管理;各个子模块只需要定时向该模块更新信息即可。)

五:RocketMQ为什么使用nameserver?

NameServer在RocketMQ中所扮演的角色:

  • NameServer 用来保存活跃的 broker 列表,包括 Master 和 Slave 。
  • NameServer 用来保存所有 topic 和该 topic 所有队列的列表。

对于RocketMQ 来说,topic 的数据在每个 Master 上是对等的,没有哪个 Master 上有 topic 上的全部数据,所以对于zookeeper的Master 选举功能在Rocket中使用不到。

六:Producer

DefaultMQProducer

        —>ClientCofig
        --->MQProducer ->MQAdmin

TransactionMQProducer

        —> DefaultMQProducer

提供多种方式发送消息的API

producer.send(msg, selector, arg, sendCallback, timeout);  

producer.sendOneway(msg, selector, arg);

producer.sendMessageInTransaction(msg, tranExecuter, arg);

在执行producer start()方法时,最终调用的是DefaultMQProducerImpl的start()方法,TransactionMQProducer在调用DefaultMQProducerImpl的start()方法前会先调用DefaultMQProducerImpl.initTransactionEnv()方法初始化线程池。

DefaultMQProducerImpl真正的实现类

七:Consumer

DefaultMQPushConsumer

            >ClientConfig
            -->MQPushConsumer—>MQConsumer-->MQAdmin

DefaultMQPushConsumerImpl真正的实现类

  • 1.主题订阅
consumer.subscribe(topic, subExpression);

consumer.unsubscribe(topic);
  • 2.注册监听
consumer.registerMessageListener(messageListener);

Listener 接口方法:
MessageListenerOrderly ->是有序的
MessageListenerConcurrently ->是无序的

new MessageListenerOrderly(){
    public ConsumeOrderlyStatus consumeMessage(List<MessageExt >
    msgs, ConsumeOrderlyContext context){
                context.setAutoCommit(true);
                return ConsumeOrderlyStatus.SUCCESS;
                //将offset更新到本地,定时更新到broker
    }
}

DefaultMQPullConsumer

        >ClientConfig
        -->MQPullConsumer—>MQConsumer-->MQAdmin

DefaultMQPullConsumerimpl真正的实现类
方法:

consumer.fetchSubscribeMessageQueues(topic);

consumer.pull(mq, subExpression, offset, maxNums, pullCallback, timeout);

consumer.pullBlockIfNotFound(mq, subExpression, offset, maxNums, pullCallback);

consumer.updateConsumerOffset(mq, offset);

consumer.fetchConsumerOffset(mq, fromStore);

八:消息一致性

rocketmq的顺序消息需要满足2点:

  • 1.Producer端保证发送消息有序,且发送到同一个队列。
SendResult sendResult = producer.send(msg,  new MessageQueueSelector() 
{ 
    @Override
    public MessageQueue select(List<MessageQueue> mqs, Message msg, Object arg)
    {
        Integer id = (Integer) arg;
        int index = id % mqs.size();        
        return mqs.get(index);
    }
     }, “AC0001”); 
}

MessageQueueSelector实现:

SelectMessageQueueByRandoom、SelectMessageQueueByHash
  • 2.consumer端保证消费同一个队列。
Consumer.registerMessageListener(new MessageListenerOrderly(){})

九:消息重复性

  • 消费端业务操作保持幂等性
  • 日志表(消费成功)

十:消息优先级

处于一个队列,可用整数来描述每条消息的优先级,在投递前先按优先级排好序,然后令优先级高的消息先投递。RocketMQ没有特意支持消息优先级,它的所有的消息都是持久化,如果按优先级排序,开销会非常大,可以通过变通方式实现类似功能,即不同优先级各对应一个队列,发送消息时根据优先级发送到与之对应的队列中。

十一:消息过滤

Broker端过滤-RocketMQ支持根据msgId、key、Header、body进行过滤。根据Message Key查询仅仅返回符合条件的最近64条数据,所以key值尽量唯一,并且有业务区分度。

十二:发送消息负载均衡

使用Roundbin方式,轮询发送消息,每个队列接收平均的消息量。也可以自定义选择发往哪个队列。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值