消息队列 RocketMQ
-
RocketMQ是一个纯Java、分布式、队列模型的开源消息中间件
- 前身是MetaQ,是阿里参考Kafka特点研发的一个队列模型的消息中间件
- 之后开源给apache基金会成为了apache的顶级开源项目
- 它具有高性能、高可靠、高实时的特点
-
基于Kafka的整体机制和架构设计,java重写推出MetaQ 1.0,主要用于解决顺序消息和海量堆积的问题
-
消息推送,流计算,充值,交易中广泛应用,并且成功经过双十一的洗礼
- 优化了慢请求,解决在海量高并发场景下降低请求对整个集群带来的抖动
- 9.996%的延迟落在了10ms以内,而99.6%的延迟在1ms以内
- 优化主要集中正在RocketMQ存储层算法优化、JVM与操作系统调优
- 用到统一存储引擎,主要解决了消息引擎高可用和成本问题
-
优秀的高可靠,高可用,高并发又低延迟的消息队列,而开源意味着你可以看到消息队列的实现
- 主要有四大核心组成部分:NameServer、Broker、Producer以及Consumer四部分
- (四大核心都是)集群部署,意味着吞吐量和高可用
- NameServer:主要开销在于维持心跳和提供Topic-Broker的关系数据
- Broker向NameServer发心跳时,会带当前自己所负责的所有Topic信息(NameServer几乎无状态)
- Broker是具体提供业务的服务器,与NS保持长连接和心跳,并定时将Topic信息注册到NS,都是基于Netty实现,存储信息,转发消息的中转角色,具有上亿级消息堆积能力,同时可严格保证消息的有序性。
- Producer,由业务系统负责产生消息,通过多种负载均衡模式发送到Broker集群,发送低延时,支持快速失败,发送消息方式:同步(接收方响应后才发,重要通知邮件、营销信息)、(不需要等响应,用户视频上传后通知启动转码服务)异步和(只负责发送信息,不等待服务器回应且没有回调函数触发,适用于某些耗时非常短但对可靠性要求并不高的场景,例如日志收集)单项
- Consumer:支持PUSH和PULL两种消费模式,支持集群消费和广播消息,提供实时消息订阅机制
- PULL:拉取信息,批量拉取到消息,应用启动消费过程
- PUSH,消息拉取,消费进度和其他内部维护工作,将消息到达时执行的回调接口留给用户应用程序来实现,不同于 Pull 的是 Push 首先要注册消费监听器,当监听器处触发后才开始消费消息。
- 主要有四大核心组成部分:NameServer、Broker、Producer以及Consumer四部分
消费模式、顺序、通信
- Clustering 集群消费(默认):多对一,下个消费组集群共同消费一个主题的多个队列,一个队列只会被一个消费者消费,如果某个消费者挂了,分组内其他消费者会接替挂掉的消费者继续消费
- Broadcasting 广播消费: 发给消费组中的每个消费者进行消费
- 消息 Order
- Orderly 顺序 (需要保证主题Topic只有一个消费序列,顺序保持一致)
- Concurrently 并行(不保证顺序,最大并行数量受每个消费者客户端指定的线程池限制)
- 通信流程
- Producer 与 NameServer集群中的其中一个节点(随机选择)建立长连接
- 定期从 NameServer 获取 Topic 路由信息
- 向提供 Topic 服务的 Broker Master 建立长连接,且定时向 Broker 发送心跳。
- PS:Producer 只能将消息发送到 Broker master,但是 Consumer 则不一样,它同时和提供 Topic 服务的 Master 和 Slave 建立长连接,既可以从 Broker Master 订阅消息,也可以从 Broker Slave 订阅消息。
优缺点
-
优点
- 单机吞吐量:10w级,消息堆积10亿级别,不会因为堆积导致性能下降
- 可用性:分布式架构,高,拓展性好
- 消息可靠性:经过参数优化可以做到0丢失
- 可以通过源码定制MQ
-
缺点
- 支持客户端语言不多,java和c++,c++不成熟
- 社区活跃度不是特别活跃
- 没有在mq核心中去实现JMS等接口,迁移起来难度较高
-
功能
-
定时消息:消息发送到Broker,不能立刻被Consumer消费,要到特定的时间点或者等待特定时间后才能被消费,但RMQ不支持任意时间精度,支持特定的level,5s,10s等
-
消息中间件功能异步解耦,重要功能就是挡住前端的数据洪峰,利用内存Buffer,堆积能力与它相关,由于内存数据多少对于对外提供的访问能力影响有心啊。因此性能下降在消息堆积后不会太大
- Broker的Buffer通常指的是Broker中一个队列的内存Buffer大小,这类Buffer通常大小有限。
- RocketMQ没有内存Buffer概念,RocketMQ的队列都是持久化磁盘,数据定期清除。即RocketMQ同其他MQ有非常显著的区别,RocketMQ的内存Buffer抽象成一个无限长度的队列,不管有多少数据进来都能装得下,这个无限是有前提的,Broker会定期删除过期的数据。
-
回溯消费
- Consumer已经消费成功的消息,由于业务上的需求需要重新消费,要支持此功能,Broker在向Consumer投递成功消息后,消息仍然需要保留,并且重新消费一般是按照时间维度。
-
消息过滤
- Broker端消息过滤
- 在Broker中,按照Consumer的要求做过滤,优点是减少了对于Consumer无用消息的网络传输。缺点是增加了Broker的负担,实现相对复杂。
- Consumer端消息过滤
- 这种过滤方式可由应用完全自定义实现,但是缺点是很多无用的消息要传输到Consumer端。
- Broker端消息过滤
-
Half Message(半消息):暂不能被Consumer消费的消息,对消息的
二次确认后,Consumer才能去消费它 -
主动询问 Producer端 该消息的最终状态(Commit或者Rollback),该消息即为 消息回查。
-
可用性:消息刷盘,RocketMQ采用的是混合型的存储结构,即为Broker单个实例下所有的队列共用一个日志数据文件(即为CommitLog)来存储。
-
缺点在于,会存在较多的随机读操作,因此读的效率偏低,同时消费消息需要依赖ConsumeQueue,构建该逻辑消费队列需要一定开销。
-
-
多线程并发:订单号+业务场景组成一个唯一主键,只有第一个成功的,可以用丢弃代替报错,减少数据库的报错
总结
- RocketMQ现在还是有些一知半解,还需要继续深入去了解