RocketMQ详解

本文深入探讨RocketMQ的架构设计,包括异步解耦、削峰限流、消息堆积处理、nameserv与brocker角色解析,以及消息生产和消费机制。涵盖push与pull消费方式对比,重试机制与重复消费解决方案,顺序消费保障,刷盘持久化策略,及集群与负载均衡技术要点。
摘要由CSDN通过智能技术生成

异步解耦,削峰限流【一群模块爆发式的调用一个比较薄弱的模块,尤其是 第三方提供的不可控模块,之前做的智慧社区项目中人们完成任务可以回去第三方小游戏的喂小鸡的粮食,不做削峰时,一到9-11点和4-5点都会出现失败问题,所以将调用第三方的薄弱接口的逻辑交给一个模块消费mq消息实现削峰】,nginx网关过滤【过滤非法值啊,配合lua校验有效性】可以削峰

消息堆积的处理方案(消费端重启时间过久可能会造成推挤):上线一个临时的consumer_tmp同组(A组)内的,跟组内别的consumer不同,他不处理业务,而是快速的将消息搬运到另外一个topic中,可以用新组(B组)的consumer来处理这些堆积的消息(这里要怎么解决可以视情况而定),consumer_tmp下线,之前的A组consumer就可以在不堆积的情况下工作。

nameserv:发现以及路由

Brocker:读写消息的地方queue【写队列给productor用,读队列consumer,读写队列是一对一的在物理上是同一个,所以数量默认一致,若写多则会有的消息消费不到,若写多则有的队列没有可消费的消息】,topic,同步刷盘、异步刷盘,定期给nameserv心跳包

productor:消息生产者,与nameserv连接,nameserv告知他“你提供的消息主题在某某些Brocker可接受”,同步发送(保证可靠性)、异步发送(快速,异步回调监听保证可靠性)、单向发送(快,不管成功与否),集群模式(一个group中消费一次,以组为单位)&广播模式

consumer:消费端,告知nameserv我的订阅内容在哪些Brocker中存在 push&poll两种方式,消费确认,同组内的consumer官方要求最好一致,消费方式consumer主动与Brocker建立长轮询【相较于短轮询,长轮询每次会等待真正的数据返回,才结束这次轮询,有点阻塞的意思;而短轮询是没有数据就直接返回空;】,拉取的时候可以一次批量拉多条,来过来处理时也可以一次处理多个

消息:topic(每个订阅了该topic的组都会有其中一个consumer收到对应消息),tag (用于过滤),key(用于存业务键),每个消费group都会接收到自己订阅的topic,消息来了之后再看tag是不是想要的。

例如

productorA:发送了一次消息:topicA,tagZ,"megbodyAxxxx"

consumer甲-1:属于甲组,订阅topicA,tagY   他会收到上边那条消息但是会过滤啥也不干

consumer乙-1:属于乙组,订阅topicA,tagZ   他会收到上边那条消息,进行业务处理

复杂的过滤,tag 无法满足时可以使用类sql方式

productor发送事务消息:先发出去消息标记为“待确认半消息”,任务事务可提交了将消息改为“已确认”(提交事务跟消息改为已确认在一个事务方法中完成),只有变为已确认的消息才能被消费。多用于分布式事务实现最终一致性,需实现监听器的两个方法:一个事物本身,一个回调检测方法

消费端获得消息的方式:

  1. push方式里,consumer把轮询过程封装了,并注册MessageListener监听器,取到消息后,唤醒MessageListener的consumeMessage()来消费,对用户而言,感觉消息是被推送过来的,实际还是主动建立长轮询获取消息。
  2. pull方式里,取消息的过程需要用户自己写,首先通过打算消费的Topic拿到MessageQueue的集合,遍历MessageQueue集合,然后针对每个MessageQueue批量取消息,一次取完后,记录该队列下一次要取的开始offset,直到取完了,再换另一个MessageQueue。
  3. push实时性高,但增加服务端负载,消费端能力不同,如果push的速度过快,消费端消费慢【异步执行监听器中处理消息的业务逻辑】会造成客户端消息拥堵

  4. pull消费者从server端拉消息,主动权在消费端,可控性好,但是时间间隔不好设置,间隔太短,则空请求会多,浪费资源,间隔太长,则消息不能及时处理

 

重试机制:

  1. 服务提供失败,重新发送消息;
  2. 消费时如果出现异常可以返回“之后在消费”,消息可以再次被组内消费
  3.  消费失败消息进入重试队列、重试超过16次进入死信队列【进入死信队列就需要人工干预了】

重复消费:consumer返回的ack没有被Brocker收到,所以要保证消费端的事务幂等性

顺序消费:生产时将需要有序的消息放到同一个queue中,MessageQueueSelector;消费时保证组内一个线程去消费一个queue,多个queue只能保证队内有序,消费监听器使用特殊的有序监听器:MessageListenerOrderly

刷盘 持久化:默认文件系统,使用mmap文件关系映射实现对磁盘文件的零拷贝操作,为了满足零拷贝没打个文件大小固定1G(超过1.5G mmap的缺页中断式的加载就得分多次)

commitLog文件:用于存储真正的消息数据(mmap方式访问操作),结构  mappedFileQueue/mappedFile(每个mappedFile 1G),默认超过48小时未被访问过的文件会被删除

consumQueue文件:按照topic的queue建立的索引结构,内部存的是对应消息在commitLog中的位置

index文件:建立时间和key的索引结构【按时间范围索引,或者按key索引】,内部存的是对应消息在commitLog中的位置

当某个消息所有的订阅组都消费成功了,消息才被删除

同步刷盘  异步刷盘(都是每隔10秒进行一次磁盘顺序写入,因为直接操作的mmapBuffer所以速度更快,所以比db的方式快)

Brocker定期发送心跳告知nameserv自身管理的信息,nameserv若长期收不到心跳认定Brocker宕掉了

集群相关:

 Brocker可以做master集群,每个master维护不同的queue信息【可以是同一个topic但是queue不一样,master之间不能有重复信息】,每个master可以有一个或多个salve做主从复制达到高可用,和增加吞吐量。同一组Brocker的master和slave的BrockerName一样,BrockerId不一样master=0 slave>0,master向slave同步复制信息,复制操作也分同步【又叫同步双写,就是主从都成功才算成功,慢但保证可靠性】和异步,所以productor只连master 而consumer可以都连接

一般为了兼备集群相应速度和可靠性一般采用同步双写+异步刷盘的方式;

负载均衡:

  1. 为了满足负载需要不要使用自动方式创建queue,手动通过命令行创建读写queue位置,让其均衡分不到不同的Brocker上
  2. 生产时的负载均衡:获取到可以发送消息的queue,顺序使用他们发送【如果失败了,还会再次发往原来那个queue,因为不知道是不是真的失败了】,也可指定发送哪个queue,来实现发送时的负载均衡
  3. 消费时的负载均衡:自带组内负载均衡策略:平均分配、环形分配、

 

一些常见面试问题:

为什么用nameserver不用已有的Zookeeper?
ZooKeeper 的功能很强大,包括自动 Master 选举等, RocketMQ 的架构设计决定了它不需要进行 Master选举,用不到这些复杂的功能,只需要一个轻量级的元数据服务器就足够了 。
中间件对稳定性要求很高, RocketMQ的 NameServer只有很少的代码,容易维护,所以不需要再依赖另一个中间件,从而减少整体维护成本 
 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值