RocketMQ的架构设计、关键特性、与应用场景详解
内容大纲:
1.RocketMQ的简介与演进
2. RocketMQ的架构设计
3.RocketMQ的关键特性
4.RocketMQ的应用场景
RocketMQ的简介
RocketMQ一个纯java、分布式、队列模型的开源消息中间件,前身是MetaQ,是阿里研发的一个队列模型的消息中间件,后开源给apache基金会成为了apache的顶级开源项目,具有高性能、高可靠、高实时、分布式特点。

RocketMQ的演进
RocketMQ一共前后经历了三代演进:
1.第一代,推模式
数据存储采用关系型数据库,典型代表包括Notify、Napoli。
2.第二代,拉模式
自研的专有消息存储,在日志处理方面参考Kafka,典型代表MetaQ。
3.第三代,以拉模式为主,兼有推模式
低延迟消息引擎RocketMQ,在二代功能特性的基础上,为电商金融领域添加了可靠重试、基于文件存储的分布式事务等特性。使用在了阿里大量的应用上,典型如双11场景,具有万亿级消息流转。
RocketMQ的架构设计
1.RocketMQ的核心组件

RocketMQ主要由NameServer、Broker、Producer以及Consumer四部分构成。

1)NameServer:主要负责对于源数据的管理,包括了对于Topic和路由信息的管理。
NameServer是一个功能齐全的服务器,其角色类似Dubbo中的Zookeeper,但NameServer与Zookeeper相比更轻量。主要是因为每个NameServer节点互相之间是独立的,没有任何信息交互。
备注:下面的消息类型有Topic的介绍。
2) Producer
消息生产者,负责产生消息,一般由业务系统负责产生消息。
- Producer由用户进行分布式部署,消息由Producer通过多种负载均衡模式发送到Broker集群,发送低延时,支持快速失败。
3 )Broker
消息中转角色,负责存储消息,转发消息。
- Broker是具体提供业务的服务器,单个Broker节点与所有的NameServer节点保持长连接及心跳,并会定时将Topic信息注册到NameServer,顺带一提底层的通信和连接都是基于Netty实现的。
- Broker负责消息存储,以Topic为纬度支持轻量级的队列,单机可以支撑上万队列规模,支持消息推拉模型。
- 官网上有数据显示:具有上亿级消息堆积能力,同时可严格保证消息的有序性。
4)Consumer
消息消费者,负责消费消息,一般是后台系统负责异步消费。
- Consumer也由用户部署,支持PUSH和PULL两种消费模式,支持集群消费和广播消息,提供实时的消息订阅机制。
5)大致流程
Broker在启动的时候会去向NameServer注册并且定时发送心跳,Producer在启动的时候会到NameServer上去拉取Topic所属的Broker具体地址,然后向具体的Broker发送消息。具体如下图:

2.RocketMQ的消息领域模型
主要分为Message、Topic、Queue、Offset以及Group这几部分。

1)Topic
Topic表示消息的第一级类型,比如一个电商系统的消息可以分为:交易消息、物流消息等。一条消息必须有一个Topic。
最细粒度的订阅单位,一个Group可以订阅多个Topic的消息。
2)Tag
Tag表示消息的第二级类型,比如交易消息又可以分为:交易创建消息,交易完成消息等。RocketMQ提供2级消息分类,方便灵活控制。
3)Group
组,一个组可以订阅多个Topic。
4)Message Queue
消息的物理管理单位。一个Topic下可以有多个Queue,Queue的引入使得消息的存储可以分布式集群化,具有了水平扩展能力。
在
RocketMQ 中,所有消息队列都是持久化,长度无限的数据结构,所谓长度无限是指队列中的每个存储单元都是定长,访问其中的存储单元使用
Offset 来访问,offset 为 java long 类型,64 位,理论上在 100年内不会溢出,所以认为是长度无限。
也可以认为 Message Queue 是一个长度无限的数组,Offset 就是下标。
RocketMQ的关键特性
1.消息的顺序
消息的顺序指的是消息消费时,能按照发送的顺序来消费。例如:一个订单产生了 3 条消息,分别是订单创建、订单付款、订单完成。消费时,要按照这个顺序消费才有意义。但同时订单之间又是可以并行消费的。
RocketMQ是通过将“相同ID的消息发送到同一个队列,而一个队列的消息只由一个消费者处理“来实现顺序消息。如下图:

这样对于同一个订单的创建、付款和完成消息,确保按照这一顺序被发送和消费。
2.消息重复
1)消息重复的原因
消息领域有一个对消息投递的QoS定义,分为:
- 最多一次(At most once)
- 至少一次(At least once)
- 仅一次( Exactly once)
QoS:Quality of Service,服务质量
几乎所有的MQ产品都声称自己做到了At
least
once。既然是至少一次,那避免不了消息重复,尤其是在分布式网络环境下。比如:网络原因闪断,ACK返回失败等等故障,确认信息没有传送到消息队列,导致消息队列不知道自己已经消费过该消息了,再次将该消息分发给其他的消费者。
不同的消息队列发送的确认信息形式不同,例如RabbitMQ是发送一个ACK确认消息,RocketMQ是返回一个CONSUME_SUCCESS成功标志,kafka实际上有个offset的概念。
RocketMQ没有内置消息去重的解决方案,最新版本是否支持还需确认。
2)消息去重
1)去重原则:使用业务端逻辑保持幂等性
幂等性:就是用户对于同一操作发起的一次请求或者多次请求的结果是一致的,不会因为多次点击而产生了副作用,数据库的结果都是唯一的,不可变的。
只要保持幂等性,不管来多少条重复消息,最后处理的结果都一样,需要业务端来实现。
2)去重策略:保证每条消息都有唯一编号(比如唯一流水号),且保证消息处理成功与去重表的日志同时出现。
建立一个消息表,拿到这个消息做数据库的insert操作。给这个消息做一个唯一主键(primary key)或者唯一约束,那么就算出现重复消费的情况,就会导致主键冲突,那么就不再处理这条消息。
RocketMQ的应用场景
1.削峰填谷
比如如秒杀等大型活动时会带来较高的流量脉冲,如果没做相应的保护,将导致系统超负荷甚至崩溃。如果因限制太过导致请求大量失败而影响用户体验,可以利用MQ 超高性能的消息处理能力来解决。
2.异步解耦
通过上、下游业务系统的松耦合设计,比如:交易系统的下游子系统(如积分等)出现不可用甚至宕机,都不会影响到核心交易系统的正常运转。
3.顺序消息
与FIFO原理类似,MQ提供的顺序消息即保证消息的先进先出,可以应用于交易系统中的订单创建、支付、退款等流程。
4.分布式事务消息
比如阿里的交易系统、支付红包等场景需要确保数据的最终一致性,需要引入 MQ 的分布式事务,既实现了系统之间的解耦,又可以保证最终的数据一致性。
将大事务拆分成小事务,减少系统间的交互,既高效又可靠。再利用MQ 的可靠传输与多副本技术确保消息不丢,At-Least-Once 特性来最终确保数据的最终一致性。
RocketMQ两种消息消费方式
推拉模式的时候指的是 Comsumer 和 Broker 之间的交互。
推模式
broker主动推消息给消费者,来一条推一条
优点:来一条推一条,实时性较高
缺点:消费者的消费能力有限,如果一时间大量的消息推过来 消费者并没有能力一下去消费这么多。不同的消费者消费速率可能不同,导致broker维护不同消费者推送速率较困难.
适用于: 消息量不大,消息实时性要求高场景
拉模式
消费者主动的去broker拉消息,消费者可根据自己的消费能力去拉消息
优点:broker只需要存储好生产者发来的数据,具体谁来拉 什么时候拉都不用管了。可以支持批量拉取,消费者根据自身条件选择批量拉取
缺点:消息延迟,消费者可能两秒发一次请求向broker拉数据(不能过于频繁)。 消息忙请求(可能连续拉了几个小时一条消息都没有,做无用功)
RocketMQ 和 Kafka 都选择了拉模式,当然业界也有基于推模式的消息队列如 ActiveMQ
消费者各种各样,身为 Broker 不应该有依赖于消费者的倾向,而是主要负责存储消息,方便消费者自己来拉消息。
RocketMQ 和 Kafka 都是利用“长轮询”来实现拉模式,
长轮询
RocketMQ长轮询
主要是两方面,
一个就是生产者发送拉消息请求到broker,判断一下当前是否有新消息,有就直接返回,没有轮询等待(每5秒重新查一次有没有新消息到了)
再一个就类似观察者模式,消费者的请求会放入pullRequestTable中,新消息来了会通知所有观察者消息到了。
Kafka长轮询
消费者底层最终会调用 Java nio 的 select(timeout),发送请求到broker。
消费者和 Broker 相互配合,拉取消息请求不满足条件的时候 hold 住,避免了多次频繁的拉取动作,当消息一到就提醒返回。
RocketMQ消息消费本质上是基于的拉(pull)模式,consumer主动向消息服务器broker拉取消息。
consumer被分为2类:MQPullConsumer和MQPushConsumer,其实本质都是拉模式(pull),即consumer轮询从broker拉取消息。 区别:
MQPushConsumer方式,consumer把轮询过程封装了,并注册MessageListener监听器,取到消息后,唤醒MessageListener的consumeMessage()来消费,对用户而言,感觉消息是被推送(push)过来的。主要用的也是这种方式。
MQPullConsumer方式,取消息的过程需要用户自己写,首先通过打算消费的Topic拿到MessageQueue的集合,遍历MessageQueue集合,然后针对每个MessageQueue批量取消息,一次取完后,记录该队列下一次要取的开始offset,直到取完了,再换另一个MessageQueue。
数据交互有两种模式:Push(推模式)、Pull(拉模式)。真正的PUSH和PULL的区别:
推模式指的是客户端与服务端建立好网络长连接,服务方有相关数据,直接通过长连接通道推送到客户端。其优点是及时,一旦有数据变更,客户端立马能感知到;另外对客户端来说逻辑简单,不需要关心有无数据这些逻辑处理。缺点是不知道客户端的数据消费能力,可能导致数据积压在客户端,来不及处理。
拉模式指的是客户端主动向服务端发出请求,拉取相关数据。其优点是此过程由客户端发起请求,故不存在推模式中数据积压的问题。缺点是可能不够及时,对客户端来说需要考虑数据拉取相关逻辑,何时去拉,拉的频率怎么控制等等。
拉模式中,为了保证消息消费的实时性,采取了长轮询消息服务器拉取消息的方式。每隔一定时间,客户端想服务端发起一次请求,服务端有数据就返回数据,服务端如果此时没有数据,保持连接。等到有数据返回(相当于一种push),或者超时返回。
长轮询Pull的好处就是可以减少无效请求,保证消息的实时性,又不会造成客户端积压。
目前绝大部分的MQ都是基于的PULL模式。
————————————————
两种消息消费方式:pull拉、push推
1、推送方式pull模式:
拉取,DefaultMQPullConsumer模式。
是由客户端主动向MQ请求数据,主动权在客户端,先拉取数据再消费。不会因为推送太快而处理不及时。
2、push模式:
推送,DefaultMQPushConsumer模式。
一般的push是MQ主动推送信息,但是可能会导致消费者跟不上推送速度。RocketMQ采用的是长轮询的方式,客户端访问MQ,有信息就拉取关闭连接消费,然后再请求并拉取。没有信息请求就会等待新信息,知道超时,超时会关闭连接并再次发送新的请求。
RocketMQ的架构设计、关键特性、与应用场景详解的更多相关文章
- linux驱动由浅入深系列:高通sensor架构实例分析之三(adsp上报数据详解、校准流程详解)【转】
本文转载自:https://blog.csdn.net/radianceblau/article/details/76180915 本系列导航: linux驱动由浅入深系列:高通sensor架构实例分 ...
- Android 高级UI设计笔记07:RecyclerView 的详解
1. 使用RecyclerView 在 Android 应用程序中列表是一个非常重要的控件,适用场合非常多,如新闻列表.应用列表.消息列表等等,但是从Android 一出生到现在并没有非常 ...
- 大数据Hadoop核心架构HDFS+MapReduce+Hbase+Hive内部机理详解
微信公众号[程序员江湖] 作者黄小斜,斜杠青年,某985硕士,阿里 Java 研发工程师,于 2018 年秋招拿到 BAT 头条.网易.滴滴等 8 个大厂 offer,目前致力于分享这几年的学习经验. ...
- Hadoop核心架构HDFS+MapReduce+Hbase+Hive内部机理详解
转自:http://blog.csdn.net/iamdll/article/details/20998035 分类: 分布式 2014-03-11 10:31 156人阅读 评论(0) 收藏 举报 ...
- 云时代架构阅读笔记六——Java内存模型详解(二)
承接上文:云时代架构阅读笔记五——Java内存模型详解(一) 原子性.可见性.有序性 Java内存模型围绕着并发过程中如何处理原子性.可见性和有序性这三个特征来建立的,来逐个看一下: 1.原子性(At ...
- iOS10新特性之CallKit开发详解:锁屏接听和来电识别
国庆节过完了,回家好好休息一天,今天好好分享一下CallKit开发.最近发现好多吃瓜问CallKit的VoIP开发适配,对iOS10的新特性开发和适配也在上个月完成,接下来就分享一下VoIP应用如何使 ...
- Android 高级UI设计笔记19:PopupWindow使用详解
1. PopupWindow使用 PopupWindow这个类用来实现一个弹出框,可以使用任意布局的View作为其内容,这个弹出框是悬浮在当前activity之上的. 2. PopupWindow使用 ...
- 让互联网更快,Server Push 特性及开启方式详解
过去 Nginx 并不支持 HTTP/2 的 Server Push 特性,幸运的是 Nginx 1.13.9 已支持该特性,详情介绍请移步 Nginx 官方博客. Server Push 这个特性是 ...
- 【repost】H5的新特性及部分API详解
h5新特性总览 移除的元素 纯表现的元素: basefont.big.center.font等 对可用性产生负面影响的元素: frame.frameset.noframes 新增的API 语义: 能够 ...
- 第十一章: Hadoop核心架构HDFS+MapReduce+Hbase+Hive内部机理详解
HDFS的体系架构 整个Hadoop的体系结构主要是通过HDFS来实现对分布式存储的底层支持,并通过MR来实现对分布式并行任务处理的程序支持. HDFS采用主从(Master/Slave)结构模型,一 ...
随机推荐
- 机器学习中验证两个算法之间是否存在显著差距的t-test检验
同一主题的简单分析版本,建议查看: 机器学习领域中假设检验的使用 本文内容为在上文基础上进一步分析版本. 相关: t检验 t检验应用条件 t检验(t-test) t-test终极指南 一文详解t检验 ...
- Netty 如何自动探测内存泄露的发生
本文基于 Netty 4.1.112.Final 版本进行讨论 本文是 Netty 内存管理系列的最后一篇文章,在第一篇文章 <聊一聊 Netty 数据搬运工 ByteBuf 体系的设计与实现& ...
- html中input标签放入小图标
直接上代码 <style type="text/css"> *{ margin: 0; padding: 0; } .box{ width: 200px; positi ...
- P5524 Ynoi2012 NOIP2015 充满了希望
P5524 Ynoi2012 NOIP2015 充满了希望 数组开大见祖宗. 思路 不难发现只有询问才会产生贡献,而询问的值来自于距离它最近的且能覆盖这个询问的点的覆盖操作. 可以每个询问操作保存一个 ...
- JAVA反序列化学习-前置知识(基于ysoserial)
本人在学习Java反序列化中,发现网上大多都是自己分析一些逻辑内容,导致可能每一个版本的payload都不相同,对于学习时并不友好,所以我在学习了cc链之后,准备总结一下cc链中的内容,并以ysose ...
- tsconfig配置详解
{ "compilerOptions": { /* Basic Options */ "target": "es5" /* target用于 ...
- bootstrap table 搜索只从当前页开始搜
项目中出现的情况,使用bootstrap table框架,使用搜索功能的是后查询的结果不是从第一也开始,有时候点击搜索第一次查不出来结果,点击第二次结果才出现. 解决方法: $("#btn_ ...
- Checking Table 设计模式 - 从概念、建模、设计到实现——兼谈基于业务需求驱动的设计模式创新
郑 先全, 架构师, NEC Asia Pacific Pte Ltd 简介: 如何基于业务需求驱动理念来开展我们的模式创新,成为了当今架构师.设计师的重要职责之一.本文通过具体的 Checking ...
- 十亿手机号去重-BitSet
思路:使用Java自带BitSet函数,将手机号分为两段(15555555555 -> 155+55555555) public class demo { public static void ...
- 如何TypeScript中相对优雅地实现类的多继承
首先,在 js 中还没有真正的多继承.但是在实际工作中经常需要抽离通用模块并按需组成新的业务模块,这就对类的多继承有了实际需求. 举个例子,现在我们有个基础类 Animal : class Anima ...