基本组件
NameServer: 注册中心 ,主要提供两个功能:Broker管理 和 路由信息管理。消费者和生产者就从 NameServer 中获取路由表然后照着路由表的信息和对应的 Broker 进行通信。
Broker:消息队列服务器嘛,生产者生产消息到 Broker ,消费者从 Broker 拉取消息并消费。
Producer:生产者。
Consumer:消费者,支持以push推,pull拉两种模式对消息进行消费。同时也支持集群方式和广播方式的消费,它提供实时消息订阅机制。
Broker 做了集群并且还进行了主从部署,salve 定时从 master 同步数据,如果 master 宕机,则 slave 提供消费服务,但是不能写入消息。
单个 Broker 和所有 NameServer 保持长连接 ,并且在每隔30秒 Broker 会向所有 Nameserver 发送心跳,心跳包含了自身的 Topic 配置信息。
在生产者需要向 Broker 发送消息的时候,需要先从 NameServer 获取关于 Broker 的路由信息,然后通过 轮询 的方法去向每个队列中生产数据以达到 负载均衡 的效果。
消费者通过 NameServer 获取所有 Broker 的路由信息后,向 Broker 发送 Pull 请求来获取消息数据。Consumer 可以以两种模式启动—— 广播(Broadcast)和集群(Cluster)。广播模式下,一条消息会发送给 同一个消费组中的所有消费者 ,集群模式下消息只会发送给一个消费者
顺序消费
RocketMQ 在主题上是无序的、它只有在队列层面才是保证有序 的。
普通顺序:普通顺序是指 消费者通过 同一个消费队列收到的消息是有顺序的,普通顺序消息在 Broker 重启情况下不会保证消息顺序性。
严格顺序:严格顺序是指 消费者收到的 所有消息 均是有顺序的。严格顺序消息 即使在异常情况下也会保证消息的顺序性 。
对于同一订单来说,我们必须要保证订单的创建、支付、发货是有序的,但是同一个 topic 下,不同的队列是不能保证顺序,此时可以通过 hash 取模法,来将消息发送到同一个队列里,同一个队列里消息是保证有序的。
重复消费
解决重复消费用幂等操作,实现幂等有使用 redis 的 key 和 value,set 操作是幂等的。或者使用数据库唯一键保证不插入重复数据来实现幂等。
分布式事务:
RocketMQ 采用事务消息加上事务反查机制来保证消息发送的分布式事务的。

第一步:Producer 发送 half 消息(不可见,不可消费的消息),
第二步:MQ 收到消息后响应 Producer
第三步:Producer 处理事务
第四步:根据 Producer 事务执行情况进行 MQ 端的 commit 或者 rollback
第五步:如果第四步出现问题(网络波动),没有接受到消息是需要 commit 还是 rollback,回向 Producer 反查该消息的事务情况
第六步:Producer 检查该消息的事务
第七步:根据结果再次响应该消息是否该 commit 或者 rollback
消息堆积问题
消息堆积的两种情况,Producer 生产太快,Consumer 消费太慢。
对于 Producer 生产太快,可以采用限流降级的办法处理。
对于 Consumer 消费太慢,可以采用增加消费者,同时增加队列的方式提高消费速度(一一个队列只有一个消费者消费)。
回溯消费
回溯消费,即重新消费之前消费过数据,RocketMQ 支持按照时间维度回溯消费,时间维度精确到毫秒。
RocketMQ 的刷盘机制
RocketMQ 支持同步刷盘和异步刷盘
同步刷盘:消息写入磁盘成功,才 ACK,对性能影响较大,但是消息可靠,不会丢失,一般用在金融等特点场景。
异步刷盘:开启一个线程去异步地执行刷盘操作。消息刷盘采用后台异步线程提交的方式进行。降低了读写延迟,提高了性能和吞吐量,一般适用于如发验证码等对于消息保证要求不太高的业务场景。
一般地,异步刷盘只有在 Broker 意外宕机的时候会丢失部分数据。
同步复制和异步复制
同步复制: 也叫 “同步双写”,也就是说,只有消息同步双写到主从结点上时才返回写入成功 。
异步复制:消息写入主节点之后就直接返回写入成功。
## 存储机制
RocketMQ 消息存储架构中的三大角色——CommitLog 、ConsumeQueue 和 IndexFile
CommitLog: 消息主体以及元数据的存储主体,存储 Producer 端写入的消息主体内容,消息内容不是定长的。单个文件大小默认1G ,文件名长度为20位,左边补零,剩余为起始偏移量,比如00000000000000000000代表了第一个文件,起始偏移量为0,文件大小为1G=1073741824;当第一个文件写满了,第二个文件为00000000001073741824,起始偏移量为1073741824,以此类推。消息主要是顺序写入日志文件,当文件满了,写入下一个文件。
ConsumeQueue: 消息消费队列,引入的目的主要是提高消息消费的性能(我们再前面也讲了),由于RocketMQ 是基于主题 Topic 的订阅模式,消息消费是针对主题进行的,如果要遍历 commitlog 文件中根据 Topic 检索消息是非常低效的。Consumer 即可根据 ConsumeQueue 来查找待消费的消息。其中,ConsumeQueue(逻辑消费队列)作为消费消息的索引,保存了指定 Topic 下的队列消息在 CommitLog 中的起始物理偏移量 offset ,消息大小 size 和消息 Tag 的 HashCode 值。consumequeue 文件可以看成是基于 topic 的 commitlog 索引文件,故 consumequeue 文件夹的组织方式如下:topic/queue/file三层组织结构,具体存储路径为:$HOME/store/consumequeue/{topic}/{queueId}/{fileName}。同样 consumequeue 文件采取定长设计,每一个条目共20个字节,分别为8字节的 commitlog 物理偏移量、4字节的消息长度、8字节tag hashcode,单个文件由30W个条目组成,可以像数组一样随机访问每一个条目,每个 ConsumeQueue文件大小约5.72M;
IndexFile: IndexFile(索引文件)提供了一种可以通过key或时间区间来查询消息的方法。这里只做科普不做详细介绍
参考资料1:RocketMQ入门总结