RocketMQ基本概念

《RocketMQ实战与原理解析》学习笔记
引用: https://yq.aliyun.com/articles/602084
引用: https://www.jianshu.com/p/d06e9bc6c463

在这里插入图片描述
由上图可知,rocketmq主要包括如下4部分: NameServer 集群、Broker 集群、Producer 集群和 Consumer 集群。

naemsrv

对于一个消息队列集群来说,系统由很多台机器组成,每个机器的角色、IP地址都不相同,而且这些信息是变动的。
这种情况下,如果一个新的Producer或Consumer加入,怎么配置连接信息呢?
naemsrv的存在主要是为了解决这类问题,由naemsrv维护这些配置信息、状态信息,其他角色都通过naemsrv来协同执行。

naemsrv的功能

naemsrv是RocketMQ集群的协调者,集群的各个组件是通过naemsrv获取各种属性和地址信息的。
主要功能包括两部分:

  • broker定时向naemsrv发送心跳(上报自己的状态信息),维护可用broker地址。超时不上报的话,naemsrv会认为某个机器出故障不可用了
  • Producer、Consumer,以及命令行工具,通过naemsrv获取最新的状态信息(如可用的broker信息)。

naemsrv集群部署

naemsrv可以部署多个,相互之间独立,其他角色同时向多个naemsrv机器上报状态信息,从而达到热备份的目的。
naemsrv本身是无状态的,也就是说naemsrv中的Broker、Topic等状态信息不会持久存储,
都是由各个角色定时上报并存储到内存中的(naemsrv支持配置参数的持久化,一般用不到)

naemsrv之间不存在主备切换过程,如果其中一台naemsrv宕机后,生产者消费者会直接从另一台naemsrv中请求数据。

naemsrv动态扩容

但是naemsrv之间不存在心跳检测,所以无法支持动态扩容.
在启动Broker、生产者和消费者之前,必须告诉它们naemsrv的地址,为了提高可靠性,建议启动多个naemsrv。
naemsrv占用资源不多,可以和Broker部署在同一台机器。有多个naemsrv后,减少某个naemsrv不会对其他组件产生影响。
有四种种方式可设置naemsrv的地址,下面按优先级由高到低依次介绍:

  1. 通过代码设置,
    • 比如在Producer中,通过producer.setNamesrvAddr("s157:9876;s158:9876");来设置。
    • 在mqadmin命令行工具中,通过-n s157:9876;s158:9876来设置
  2. 使用Java启动参数设置,对应的-Drocketmq.namesrv.addr=xxx
  3. 通过Linux环境变量设置,在启动前设置变量:export NAMESRV_ADDR=s157:9876;s158:9876
  4. 通过HTTP服务来设置,当上述方法都没有使用,程序会向一个HTTP地址发送请求来获取naemsrv地址,
    默认的URL是http://jmenv.tbsite.net:8080/rocketmq/nsaddr(淘宝的测试地址)
    通过rocketmq.namesrv.domain参数来覆盖jmenv.tbsite.net
    通过rocketmq.namesrv.domain.subgroup参数来覆盖nsaddr

第4种方式看似繁琐,但它是唯一支持动态增加naemsrv,无须重启其他组件的而动态获取最新的namersv,用来支持动态扩容
使用这种方式后其他组件会每隔2分钟请求一次该URL,获取最新的naemsrv地址。(broker通过updateBrokerConfig -n来动态修改namersrv)

其他方式,无法支持动态扩容,需要修改broker、consumer、producer中的namesv地址信息,并重启。

broker

Broker是RocketMQ的核心,大部分‘重量级”工作都是由Broker完成的,包括

  • 接收Producer发过来的消息
  • 处理Consumer的消费消息请求
  • 消息的持久化存储
  • 消息的HA机制
  • 服务端过滤功能等。

HA机制
1、目前它支持master写操作,只有当master读压力高于某个点(master消息拉取出现堆积时),才会将读压力转给salver。
2、无法做到主从切换,master宕机,salver只能提供消息消费,salver不会被选举为master来继续工作。

高可用

RocketMQ分布式集群是通过Master和Slave的配合达到高可用性的,
首先说一下Master和Slave的区别:

  • 在Broker的配置文件中,的值为0表明这个Broker是Master,大于0表明这个Broker是Slave,
  • 同时brokerRole参数也会说明这个Broker是Master还是Slave。
    在这里插入图片描述
    Master角色的Broker支持读和写,Slave角色的Broker仅支持读,也就是
  • Producer只能和Master角色的Broker连接写入消息;
  • Consumer可以连接Master角色的Broker,也可以连接Slave角色的Broker来读取消息。

broker读高可用
在Consumer的配置文件中,并不需要设置是从Master读还是从Slave读,当Master不可用或者繁忙的时候,Consumer会被自动切换到从Slave读。
有了自动切换Consumer这种机制,当一个Master角色的机器出现故障后,Consumer仍然可以从Slave读取消息,不影响Consumer程序。这就达到了消费端的高可用性。

broker写高可用
在创建Topic的时候,把Topic的多个MessageQueue创建在多个Broker组上(相同Broker名称,不同brokerId的机器组成一个Broker组),
这样当一个Broker组的Master不可用后,其他组的Master仍然可用,Producer仍然可以发送消息。

RocketMQ目前还不支持把Slave自动转成Master
如果机器资源不足,需要把Slave转成Master,则要手动停止Slave角色的Broker,更改配置文件,用新的配置文件启动Broker。

同步复制和异步复制

Broker组有Master和Slave,消息需要从Master复制到Slave上,有同步和异步两种复制方式。

  • 同步复制方式是等Master和Slave均写成功后才反馈给客户端写成功状态
  • 异步复制方式是只要Master写成功即可反馈给客户端写成功状态。

同步复制和异步复制是通过Broker配置文件里的brokerRole参数进行设置
的,这个参数可以被设置成三个值中ASYNC_MASTER、SYNC_MASTER、SLAVE的一个。

同步与异步对比
这两种复制方式各有优劣,

  • 在异步复制方式下,系统拥有较低的延迟较高的吞吐量,但是如果Master出了故障,有些数据因为没有被写人Slave,有可能会丢失
  • 在同步复制方式下,如果Master出故障,Slave上有全部的备份数据,容易恢复,但是同步复制会增大数据写人延迟降低系统吞吐量

同步刷盘和异步刷盘

RocketMQ的消息是存储到磁盘上的,这样既能保证断电后恢复,又可以让存储的消息量超出内存的限制。
RocketMQ为了提高性能,会尽可能地保证磁盘的顺序写。消息在通过Producer写人RocketMQ的时候,有两种写磁盘方式:同步刷盘和异步刷盘.

同步刷盘还是异步刷盘,是通过Broker配置文件里的flushDiskType参数设置的,这个参数被配置成SYNC_FLUSH,ASYNC_FLUSH中的一个。

  • 异步刷盘方式(ASYNC_FLUSH):在返回写成功状态时,消息可能只是被写入了内存的PAGECACHE,写操作的返回快,吞吐量大;当内存里的消息量积累到一定程度时,统一触发写磁盘动作,快速写入。

  • 同步刷盘方式(SYNC_FLUSH):在返回写成功状态时,消息已经被写入磁盘。具体流程是,消息、写入内存的PAGECACHE后,立刻通知刷盘线程刷盘,然后等待刷盘完成,刷盘线程执行完成后唤醒等待的线程,返回消息写成功的状态。


生产者和消费者是消息队列的两个重要角色,生产者向消息队列写人数据,消费者从消息队列里读取数据。

consumer

根据使用者对读取操作的控制情况,消费者可分为两种类型:

  • 一个是DefaultMQPushConsumer,由系统控制读取操作,收到消息后自动调用传人的处理方法来处理(broker主动向consumer推送)
  • 另一个是DefaultMQPul!Consumer,读取操作中的大部分功能由使用者自主控制(consumer从broker拉取)

ConsumerGroup
Consumer的GroupName用于把多个Consumer组织到一起,提高并发处理能力,GroupName需要和消息模式(MessageModel)配合使用。

RocketMQ支持两种消息模式

  • Clustering:同一个ConsumerGroup(GroupName相同)里的每个Consumer只消费所订阅消息的一部分内容,同一个ConsumerGroup里所有的Consumer消费的内容合起来才是所订阅Topic内容的整体,从而达到负载均衡的目的。
  • Broadcasting(广播):每个Consumer都能消费到所订阅Topic的全部消息,也就是一个消息会被多次分发,被多个Consumer.

两种不同的消费方式:Push vs Pull

DefaultMQPushConsumer
系统收到消息后自动调用处理函数来处理消息,自动维护Offset,而且加入新的DefaultMQPushConsumer后会自动做负载均衡
我们仅需要做的工作只有:

  • 消费消息
  • 返回消费消息后的状态(后续会根据该状态自动的做处理);

DefaultMQPullConsumer
除去DefaultMQPushConsumer的工作外,还有额外的工作:

  • 遍历topic下所有的MessageQueue,并对多有的(或指定部分)MessageQueue来读取消息
  • 维护offsetstore: 从MessageQueue拉取消息时,要传入offset参数,随着消息的不断读取,offset值会不断增大,用户需要把offset存储下来(维护到内存,磁盘or数据库)
  • 根据不同的消息状态做不同的处理: 拉取消息的请求发出后会返回:FOUND,NO_MATCHED_MSG,NO_NEW_MSG和OFFSET_ILLEGAL 四种状态,需要根据每个状态做不同的处理 。

Push vs Pull

Push的优劣
Push方式是Server端接收到消息后,主动把消息推送给Client端,实时性高
对于一个提供队列服务的Server来说,用Push方式主动推送有很多弊端:

  • 首先是加大Server端的工作量,进而影响Server的性能;
  • 其次,Client的处理能力各不相同,Client的状态不受Server控制,如果Client不能及时处理Server推送过来的消息,会造成各种潜在问题。

Pull的优劣

  • Pull方式是Client端循环地从Server端拉取消息,主动权在Client手里,自己拉取到一定量消息后,处理妥当了再接着取。
  • Pull方式的问题是循环拉取消息的间隔不好设定,间隔太短就处在一个“忙等”的状态,浪费资源;每个Pull的时间间隔太长Server端有消息到来时有可能没有被及时处理。

Consumer的启动、关闭流程

消息队列一般是提供一个不间断的持续性服务, Consumer 在使用过程中,如何才能优雅地启动和关闭,确保不漏掉或者重复消费消息呢?

  • pull: 对于PullConsumer来说,使用者主动权很高,可以根据实际需要暂停、停止、启动消费过程
  • push: DefaultMQPushConsumer的退出,要调用shutdown()函数,以便释放资源、保存Offset等。

多知道一点
PushConsumer 在启动的时候 ,会做各种配置检查,然后连接 NameServer获取 Topic 信息,启动时如果遇到异常,比如无法连接 NameServer,程序仍然可以正常启动不报错(日 志里有 WARN 信息 ) 。 在单机环境下可以测试这种情况,启动 DefaultMQPushConsumer 时故意把 Name Server 地址填错,程序仍然可以正常启动,但是不会收到消息 。

consumer.start();

###start();后调用,及时暴露配置问题
consumer.fetchSubscribeMessageQueues("topic1");

producer

生产者向消息队列里写人消息,不同的业务场景需要生产者采用不同的写入策略。
比如:同步发送、异步发送、 延迟发送、 发送事务消息等

消息发送的返回状态有如下四种 :

  • FLUSH_DISK_TIMEOUT: 表示没有在规定时间内完成刷盘(需要Broker的刷盘策被创立设置成SYNC_FLUSH 才会报这个错误)。
  • FLUSH_SLAVE_TIMEOUT:表示在主备方式下,并且Broker被设置成SYNC_MASTER方式,没有在设定时间内完成主从同步。
  • SLAVE_NOT_AVAILABLE : 这个状态产生的场景和FLUSH_SLAVE_TIMEOUT类似,表示在主备方式下,并且Broker被设置成SYNC_MASTER,但是没有找到被配置成SLAVE的Broker。
  • SEND_OK :表示发送成功. 这个状态还可以简单理解为,没有发生上面列出的三个问题状态就是SEND_OK
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值