RocketMQ 进阶篇

1 应用场景

  • 异步处理
  • 应用解耦
  • 流量削锋 (秒杀系统多见,可以控制人数,可以缓解数据库并发压力)
  • 消息通讯 (点对点模式 、聊天室广播模式)

现在流行的消息中间件ActiveMQ,RabbitMQ,ZeroMQ,Kafka,MetaMQ,RocketMQ,都遵循一套JMS协议规范,我们可以利用JMS的一些通用协议规范去操作这些消息中间件。

2 整体介绍:

RocketMQ几个核心的模块:Producer,Consumer,Broker,NameSrv。他们之间的关系如下,其中每一部分都可以部署成集群模式

  • ProducerConsumer很好理解,顾名思义就是生产者和消费者,生产者负责生产消息,消费者负责消费消息,这2块的逻辑都是由业务使用者定义的。
  • Broker是RocketMQ的核心,Broker实现了消息的存储、拉取等功能。Broker通常以集群方式启动,并可配置主从,每个Broker上提供对指定topic的服务。
  • NameSrv是一个无状态的名称服务,可以集群部署。所有Broker启动的时候会向NameSrv注册自己的信息。Producer会根据目标topic从NameSrv获取到达指定Broker的路由信息,Consumer同理。

3 jms服务

刚才讲到jms服务,是一套基本MQ协议规范,基本所有的MQ都遵循,故有必要了解以下:

a 两种消息模型

P2P(Point to Point) 即一旦被消费,消息就不再在消息队列中,保证每个消息都能消费

Publish/Subscribe(Pub/Sub) 广播模式, 一个消息可以人人消费

b 消费方式

在JMS中,消息的产生和消费是异步的。对于消费来说,JMS的消息者可以通过两种方式来消费消息。

(1)同步:订阅者或接收者通过receive方法来接收消息,receive方法在接收到消息之前(或超时之前)将一直阻塞;

(2)异步:订阅者或接收者可以注册为一个消息监听器。当消息到达之后,系统自动调用监听器的onMessage方法。

4 topic \tag

发送消息的时候指定会指定topic(简单理解为消息分类),如果producer集合中没有会根据指定topic到namesrv获取topic发布信息TopicPublishInfo,并放入本地集合,定时从namesrv更新topic路由信息。

tag标签可以理解为更细一级的主题 ,标签可以让你的代码变得清晰连贯,还可以给RocketMQ提供更好的查询支持。

举个栗子,订单系统,topic可以设为“order”,tag设置为 orderId

如何理解topic下的队列:

比如broker1, broker2, borker3三台broker机器都配置了Topic_A
Broker1 的队列为queue0 , queue1
Broker2 的队列为queue0, queue2, queue3,
Broker3 的队列为queue0
当然一般情况下的broker的配置都是一样的 以上当broker启动的时候注册到namesrv的Topic_A队列为共6个分别为: broker1_queue0, broker1_queue1, broker2_queue0, broker2_queue1, broker2_queue2, broker3_queue0

5 producer轮询方式发送消息(保持了负载均衡)

Producer从namesrv获取的到Topic_A路由信息TopicPublishInfo :

List<MessageQueue> messageQueueList  //Topic_A的所有的队列            
AtomicInteger   sendWhichQueue        //自增整型             

每次通过原子计数器来选择轮询发送哪个队列 ,即求出

 (++sendWitchQueue)% messageQueueList.size

队列集合的下标,如果入参lastBrokerName不为空,代表上次选择的queue发送失败,这次选择应该避开同一个queue

6 顺序消息发送

有时需要保证消息的有序性,即要rocketMQ需要producer保证顺序消息按顺序发送到同一个queue中。

比如某一个USER购买流程(1)下单(2)支付(3)支付成功这三个消息需要根据特定规则将这个三个消息按顺序发送到一个queue ,步骤:

一般消息是通过轮询所有队列发送的,顺序消息可以根据业务比如说订单号orderId相同的消息发送到同一个队列, 或者同一用户userId发送到同一队列等等

messageQueueList [orderId%messageQueueList.size()]  
messageQueueList [userId%messageQueueList.size()] 

7 comsumer消费消息

offset偏移量,当comsumer准备消费消息之前,队列中可能已经存在消息,设置偏移量从第一条读 ,如果非第一次启动,那么按照上次消费的位置继续消费:

 consumer.setConsumeFromWhere(ConsumeFromWhere.CONSUME_FROM_FIRST_OFFSET);

pull 主动去拉读取;

push 添加监听器实时推送读取(观察者模式);

MessageListenerOrderly 发送顺序消息的监听 ,保证消息到达有序,消费者只允许有一个线程在接收消息,因为broker只保证是顺序到达,不保证在消费的时候也能顺序消费。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

天秤座的架构师

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

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

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

打赏作者

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

抵扣说明:

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

余额充值