RocketMQ总结
Posted 东瓜
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了RocketMQ总结相关的知识,希望对你有一定的参考价值。
多个mq如何选型
RocketMQ
- Java开发
- 集群化,效率高,每秒可处理几十万条消息
- 有消息查询界面
- 消息可靠性高
Kafka
- Scala开发
- 效率高
- 消息丢失概率大,适合做日志收集、埋点上报等业务
RabbitMQ
- erlang开发
- 对消息堆积支持不友好
ActiveMQ
- Java开发,简单、稳定,效率不高
MQ的作用
解耦
- 上游发mq,下游订阅,上游不需要关心有哪些下游系统,不需要与下游直接交互
异步
- 不需要同步执行的业务逻辑,异步处理,减少响应时间
削峰
- 后端Service可以保持固定速率消费,甚至停止消费,保证系统不被压垮
RocketMQ从消费发送到消费的执行流程
- Producer发送消息到Broker,负载均衡策略默认随机
- Broker接收消息,写入PageCage,返回成功
- Broker刷盘,消息存储Consumer queue、commit log
- Consumer从Broker拉取消息,拉取方式长轮询pull
- Consumer消费消息,处理业务逻辑
- Consumer返回ACK,更新Broker offset
- 消费失败,消息转入失败队列
- Broker的ScheduleService从重试队列拉取消息,重放这个消息
- 重试16次如果还是失败,消息进入死信队列
- 通过RocketMQ操作面板监控死信队列,手动处理
RocketMQ如何做负载均衡
Topic在Broker集群中分布式存储
Producer端:轮询
Consumer端:平均分配策略,一个队列最多被一个消费组的一个Consumer消费,一个Consumer可以消费多个队列
RocketMQ如何保证消息不丢失
1、Producer端
- 采取send()同步发消息,发送结果是同步感知的。
- 发送失败后可以重试,设置重试次数。默认3次。
producer.setRetryTimesWhenSendFailed(10);
- 集群部署,比如发送失败了的原因可能是当前Broker宕机了,重试的时候会发送到其他Broker上。
2、Broker端
- 修改刷盘策略为同步刷盘
- 修改主从复制策略为同步复制
3、Consumer端
- 消费成功后会返回ACK,更新Broker的offset
消息丢失的场景
- 异步刷盘,Broker宕机,未完成刷盘
- 异步复制,主Broker宕机,未完成复制
重复消费问题
1、造成重复消费的原因
- Consumer消费完,宕机,未返回ACK
- Consumer消费完,返回ACK,网络断开,Broker未收到
- 主Broker更新ACK,副Broker未复制,主Broker宕机
2、解决
业务方控制幂等
- 定义业务幂等字段,数据库定义为唯一键
怎么发送顺序消息
- 将消息发送到同一个队列中
- 通过重写MessageQueueSelector接口,将不同的消息发送到指定的队列
- Consumer消费的时候如果是多线程,需要先使用synchronize获取锁
- 一条消息消费失败,将阻塞整个队列,所以一般不用
RocketMQ效率高的原因
- 分区并行。每个Topic可以设置多个MessageQueue(Partition),可以对应多个消费者实现并行处理
- 顺序写磁盘。对commit log采用追加写的方式,新消息被追加到文件的末端
- 利用页缓存PageCache。Broker收到数据后,写入PageCache即算成功,由操作系统自己控制刷盘
- 零拷贝。消费者可以直接从PageCache读取数据,减少了数据复制次数,避免了用户态与内核态之间的切换
- 使用Netty框架实现高性能的网络传输
RocketMQ与Kafka的异同
1、定位
- Kafka定位高吞吐,对消息重复、丢失没严格要求,适用数据量超大的日志收集、埋点数据收集等常见
- RocketMQ思路源于Kafka,提供了更可靠的消息传输,具备高吞吐、高可用特性,适用大规模分布式系统应用
2、单机支持队列数
- Kafka队列数超过64个性能会下降,对多个Partition文件的顺序写在操作系统层面变成了随机写
- RocketMQ队列数增多效率无明显下降,因为数据存储在一个commit log
3、数据可靠性
- Kafka使用异步刷盘,异步主从复制,Producer只支持异步发送消息,且会积攒一批消息一起发
- RocketMQ支持同步刷盘,同步主从复制,Producer发送消息支持同步、异步、单向三种模式
4、当时消息
- Kafka不支持
- RocketMQ支持level级别的定时消息
5、消息失败重试
- Kafka不支持
- RocketMQ支持时间level级别的重试
以下RocketMQ支持,Kafka不支持:
6、分布式事务消息
7、顺序消息
8、消息查询
9、消息回溯
RocketMQ消息底层存储模型
- CommitLog存储真正的消息体
- ConsumerQueue是CommitLog的索引文件,存储消息在CommitLog的物理偏移量,消息大小,tag的hashCode
- IndexFile是面板查询的索引文件
定时消息实现原理
- 延迟级别大于0表示延迟消息,将消息转存到SCHEDULE_TOPIC_XXX队列
- ScheduleService定时任务拉取延时队列中的消息(未到延时时间则延迟100毫秒再拉)
- 根据偏移量从CommitLog拉取消息体
- 恢复成原来的消息主题,将消息投递到原主题队列
消息堆积如何处理
1、增加Consumer,增加MessageQueue,增加Consumer线程数
2、新建一个Topic,先消费将消息搬运到另外一个Topic,后用新Consumer消费处理
分布式事务消息实现原理
Half Message:预处理消息,当broker收到此类消息后,会存储到RMQ_SYS_TRANS_HALF_TOPIC的消息消费队列中
检查事务状态:Broker会开启一个定时任务,消费RMQ_SYS_TRANS_HALF_TOPIC队列中的消息,每次执行任务会向消息发送者确认事务执行状态(提交、回滚、未知),如果是未知,Broker会定时去回调在重新检查。
超时:如果超过回查次数,默认回滚消息。
也就是他并未真正进入Topic的queue,而是用了临时queue来放所谓的half message,等提交事务后才会真正的将half message转移到topic下的queue。
其他
RocketMQ消费模式有几种?
消费模型由Consumer决定,消费维度为Topic。
- 集群消费
1.一条消息只会被同Group中的一个Consumer消费2.多个Group同时消费一个Topic时,每个Group都会有一个Consumer消费到数据
- 广播消费
消息将对一 个Consumer Group 下的各个 Consumer 实例都消费一遍。即即使这些 Consumer 属于同一个Consumer Group ,消息也会被 Consumer Group 中的每个 Consumer 都消费一次。
如果让你来动手实现一个分布式消息中间件,整体架构你会如何设计实现?
- 支持集群,支持快速扩容
- 消息存储模型
- 高性能
- 高可用性
- 数据0丢失的考虑
以上是关于RocketMQ总结的主要内容,如果未能解决你的问题,请参考以下文章