消息队列RocketMQ(一)
消息队列RocketMQ(一)
消息队列应用分析
消息队列: 在消息的传输过程中保存消息的容器,生产者和消费者不直接通讯,依靠队列保证消息的可靠性,避免消息间的相互影响(例如避免雪崩)。
消息队列主要角色
服务端
客户端:
-
生产者(Producer)
-
订阅者(Consumer)

应用场景
场景1
运用活动可能需要在业务逻辑中各个环节加入运营活动逻辑,而且有时效性,频繁在正常业务逻辑中添加/删除代码显然不合理且风险极大。例如各种送红包活动,有时效性,然后每次添加或者删除这个活动我们都需要修改logic层的核心代码,如下图的框架。

所以我们应对这种问题通常会引入一个MQ,不管用户起什么请求,logic都会发一个mq消息,然后起一个运营的Business logic来消费消息,他自己也有数据访问层,访问运用所用到的数据。这样即使Business logic即使挂掉了也不影响核心逻辑。

场景2
核心基础服务,可能各个业务线都会关注某些请求处理结果,不断修改代码添加业务线的通知显然不合理。
如下图电商IM系统就实现了业务解耦。

消息队列的主要作用:
-
业务解耦:
将模块间的RPC调用改为通过消息队列中转,解除系统间的耦合:提升系统稳定性,通过广播消息避免多次调用,提高编码效率。
-
异步调用(RPC异步和MQ异步不一样,RPC异步必须收到结果,MQ是纯异步,可以不需要结果):
对于无需关调用记过的场景可以通过消息队列异步处理。
-
流量削峰:
系统的吞吐量往往取决于底层存储服务的处理能力,数据访问层可以调整消费速度缓解存储服务压力,避免短暂的高峰将系统压垮。
例如:

我们可以很容易横向拓展Logic和Data Access,而DB的扩展就非常困难(分库分表,数据路由),制约性能的就是DB,所以需要MQ减少DB的压力,也减少了对Logic的QPS需求。
思考:
使用消息队列能带来很大的收益,但也会对系统架构造成一些负面影响(系统可用性,架构复杂度,排查问题路径),消息队列不能完全代替rpc,需要合理设计业务调用。
高可用及高拓展解决方案剖析
RocketMQ功能特性:
支持事务型消息
支持延时消息
支持消息重发
支持consumer端tag过滤
支持消息回放(比如push出错了没有给用户成功推送,我们就可以用消息回放进行重新消费然后push)
RocketMQ拓扑图:
Name Server(类似注册中心)
Broker
Producer
Consumer

producer从name sever拉取特定topic的broker的路由信息,然后producer就可以跟broker进行连接了,发送消息,consumer也是如此,指定特定的topic从name server拉去路由信息,然后连接broker,消费特定topic的消息。
通过增加broker即可分布式扩容。
consumer既连接Master又连接slave不是为了读写分离,而是为了可靠性,之后我会详解。
RocketMQ架构
Broker主从部署,自身消息注册在NameServer中
Client从NameServer中获取Broker信息
NameServer节点相互独立,无数据交互:
因为Broker数量少,所以我们不需要做NameServer间的数据同步,仅需要Broker给NameServer通过广播的方式定时发心跳,然后就算一开始失败,经过几次心跳后也可以完成同步。

可靠性分析:
同步刷盘:性能低可靠性高。
异步刷盘:性能高可靠性低。

异步复制(主从):提高可靠性,不丢失性能。
同步双写(主从):可靠性最高,但牺牲性能。
官方文档关于可靠性的解释:
RocketMQ支持消息的高可靠,影响消息可靠性的几种情况:
- Broker非正常关闭
- Broker异常Crash
- OS Crash
- 机器掉电,但是能立即恢复供电情况
- 机器无法开机(可能是cpu、主板、内存等关键设备损坏)
- 磁盘设备损坏
1)、2)、3)、4) 四种情况都属于硬件资源可立即恢复情况,RocketMQ在这四种情况下能保证消息不丢,或者丢失少量数据(依赖刷盘方式是同步还是异步)。
5)、6)属于单点故障,且无法恢复,一旦发生,在此单点上的消息全部丢失。RocketMQ在这两种情况下,通过异步复制,可保证99%的消息不丢,但是仍然会有极少量的消息可能丢失。通过同步双写技术可以完全避免单点,同步双写势必会影响性能,适合对消息可靠性要求极高的场合,例如与Money相关的应用。注:RocketMQ从3.0版本开始支持同步双写。
可用性分析
主从模式Master宕机:
这个Broker就会变得可读不可写(Slave还可以被继续消费)
集群搭建方式:
-
单Master模式
-
多Master模式(一个Master挂了,可以访问另一个Master,多Master也提高了存储量和吞吐量)
-
多Master多Slave模式-异步复制(提高了可靠性,一个Masker挂了后,Consumer可以继续把这个Slave的消息消费掉,然后Provider不在写入这个挂掉的Master,改为写入另一个master(比如两个Master本来各处理provider的百分之50,现在一个挂了,没挂的就处理百分之一百的))
-
多Master多Slave模式-同步双写
以上就是分布式方案(Mysql没有路由模块,需要业务解决分布式问题,所以Mysql是一个单机数据库)
RocketMQ存储原理

CommitLog:存储消息主体(生产者的负载均衡将生产的消息分配到ConsumeQueue中)
ConsumerQueue:消息消费队列(存的是在CommitLog里的索引信息,RocketMQ不丢消息考的就是minOffset;Consumer可以一次拉去一批消息,消费完后批量的会一批ACK,但也使RoketMQ有重复消费的问题,对于重复消费有严格要求的时候,我们需要做幂等处理)
IndexFile:消息索引文件
由RocketMQ的模型我们可以看到,RocketMQ有着顺序写随机读的问题。
优化手段:
-
CommitLog文件切分,默认1G
-
MMap提升文件访问性能(类似于零拷贝,我们读写一个文件,我们会经历用户态到内核态的切换,实现Read和Write操作,例如我们读的时候会先拷贝到内核空间,然后再拷贝到用户空间,写的时候也同理。MMap其实就是用户态跟内核态进行了映射,我们操作用户态的文件实质是操作内核态的文件,从而减少内核态和用户态的数据交换。)
-
SSD(机械硬盘实际上已经足够)
生产方式:
同步(sync)
异步(async)
单向(oneway)
消息消费由两种方式:
Push:消息队列主动地将消息推送给消费者(实时性高,但没有考虑客户端的消费能力)。
Pull:由消费者客户端主动向消息队列拉取消息(实时性低,可能造成大量无效请求)。
RocketMQ消费模式:
RocketMQ地消费方式相当于拉模式,但是使用了长轮询机制,来平衡Push和Pull地缺点
LongPoll:
-
Consumer发送拉去信息
-
Broker hold住请求,直到有新消息再返回
-
请求超时,Consumer再次发起请求
-
请求超时默认三十秒
消息消费方式:
集群消费:集群内竞争消费,单条消息只消费一次,各节点均匀消费Topic的消息。
组广播消费:各集群消费全量的消息,单条消息在每个集群都会被消费一次。
RocketMQ通常使用Group内竞争,Group间广播对queue的消息进行消费
浙公网安备 33010602011771号