MQ消息队列中间件基础与RocketMQ

MQ全称为Message Queue,消息队列是应用程序和应用程序之间的通信方法。
消息队列是一种“先进先出”的数据结构。

消息中间件
场景:异步、削峰、解耦

异步:
任务异步处理:将不需要同步处理的并且耗时长的操作由消息队列通知消息接收方进行异步处理。提高了应用程序的响应时间。
在这里插入图片描述

解耦
应用程序解耦合:MQ相当于一个中介,生产方通过MQ与消费方交互,它将应用程序进行解耦合
在这里插入图片描述
削峰填谷
如订单系统,在下单的时候就会往数据库写数据。但是数据库只能支撑每秒1000左右的并发写入,并发量再高就容易宕机。低峰期的时候并发也就100多个,但是在高峰期时候,并发量会突然激增到5000以上,这个时候数据库肯定卡死了。
消息被MQ保存起来了,然后系统就可以按照自己的消费能力来消费,比如每秒1000个数据,这样慢慢写入数据库,这样就不会卡死数据库了。
但是使用了MQ之后,限制消费消息的速度为1000,但是这样一来,高峰期产生的数据势必会被积压在MQ中,高峰就被“削”掉了。但是因为消息积压,在高峰期过后的一段时间内,消费消息的速度还是会维持在1000QPS,直到消费完积压的消息,这就叫做“填谷”

缺点
系统复杂性(重复消费、消息丢失、消息的顺序消费)、数据⼀致性(分布式事务)、可⽤性(MQ可能挂了)

选型:
⽬前在市⾯上⽐较主流的消息队列中间件主要有,Kafka、ActiveMQ、RabbitMQ、RocketMQ 等这⼏种。
在这里插入图片描述市场上常见的消息队列有如下:

  • ActiveMQ:基于JMS
  • RabbitMQ:基于AMQP协议,erlang语言开发,稳定性好
  • RocketMQ:基于JMS,阿里巴巴产品
  • Kafka:类似MQ的产品;分布式消息系统,高吞吐量

Kafka和RocketMQ⼀直在各⾃擅⻓的领域发光发亮。因为吞吐量、天然分布式架构更适合现在大数据的时代。

AMQP 和 JMS
MQ是消息通信的模型;实现MQ的大致有两种主流方式:AMQP、JMS。
1.2.1. AMQP
AMQP是一种协议,更准确的说是一种binary wire-level protocol(链接协议)。这是其和JMS的本质差别,AMQP不从API层进行限定,而是直接定义网络交换的数据格式。
1.2.2. JMS
JMS即Java消息服务(JavaMessage Service)应用程序接口,是一个Java平台中关于面向消息中间件(MOM)的API,用于在两个应用程序之间,或分布式系统中发送消息,进行异步通信。
1.2.3. AMQP 与 JMS 区别

  • JMS是定义了统一的接口,来对消息操作进行统一;AMQP是通过规定协议来统一数据交互的格式
  • JMS限定了必须使用Java语言;AMQP只是协议,不规定实现方式,因此是跨语言的。
  • JMS规定了两种消息模式;而AMQP的消息模式更加丰富

重复消费问题
在互联网应用中,尤其在网络不稳定的情况下,消息队列 RocketMQ 的消息有可能会出现重复,这个重复简单可以概括为以下情况:

  • 发送时消息重复

    当一条消息已被成功发送到服务端并完成持久化,此时出现了网络闪断或者客户端宕机,导致服务端对客户端应答失败。 如果此时生产者意识到消息发送失败并尝试再次发送消息,消费者后续会收到两条内容相同并且 Message ID 也相同的消息。

  • 投递时消息重复

    消息消费的场景下,消息已投递到消费者并完成业务处理,当客户端给服务端反馈应答的时候网络闪断。 为了保证消息至少被消费一次,消息队列 RocketMQ 的服务端将在网络恢复后再次尝试投递之前已被处理过的消息,消费者后续会收到两条内容相同并且 Message ID 也相同的消息。

  • 负载均衡时消息重复(包括但不限于网络抖动、Broker 重启以及订阅方应用重启)

    当消息队列 RocketMQ 的 Broker 或客户端重启、扩容或缩容时,会触发 Rebalance,此时消费者可能会收到重复消息。

重复消费处理方式(接⼝幂等)来自三太子敖丙

幂等(idempotent、idempotence)是⼀个数学与计算机学概念,常⻅于抽象代数中。
在编程中⼀个幂等操作的特点是其任意多次执⾏所产⽣的影响均与⼀次执⾏的影响相同。
幂等函数,或幂等⽅法,是指可以使⽤相同参数重复执⾏,并能获得相同结果的函数。这些函数不会影响系统状态,也不⽤担⼼重复执⾏会对系统造成改变。
例如,“setTrue()”函数就是⼀个幂等函数,⽆论多次执⾏,其结果都是⼀样的.更复杂的操作幂等保证是利⽤唯⼀交易号(流⽔号)实现.

⼀般幂等,分场景考虑,看是强校验还是弱校验,⽐如跟⾦钱相关的场景那就很关键呀,就做强校验,别不是很重要的场景做弱校验。

强校验
⽐如你监听到⽤户⽀付成功的消息,你监听到了去加GMV是不是要调⽤加钱的接⼝,那加钱接⼝下⾯再调⽤⼀个加流⽔的接⼝,两个放在⼀个事务,成功⼀起成功失败⼀起失败
每次消息过来都要拿着订单号+业务场景这样的唯⼀标识(⽐如天猫双⼗⼀活动)去流⽔表查,看看有没有这条流⽔,有就直接return不要⾛下⾯的流程了,没有就执⾏后⾯的逻辑。
在这里插入图片描述
弱校验:
⼀些不重要的场景,发短信,我就把这个id+场景唯⼀标识作为Redis的key,放到缓存⾥⾯失效时间看你场景,⼀定时间内的这个消息就去Redis判断。

消息的顺序消费
⽣产者消费者⼀般需要保证顺序消息的话,可能就是⼀个业务场景下的,⽐如订单的创建、⽀付、发货、收货。
那这些东⻄是不是⼀个订单号呢?
一个订单的顺序流程是:创建、付款、推送、完成。订单号相同的消息会被先后发送到同一个队列中,消费时,同一个OrderId获取到的肯定是同一个队列
⼀个topic下有多个队列,为了保证发送有序,RocketMQ提供了MessageQueueSelector队列选择机制,他有三种实现:
在这里插入图片描述我们可使⽤Hash取模法,让同⼀个订单发送到同⼀个队列中,再使⽤同步发送,只有同个订单的创建消息发送成功,再发送⽀付消息。这样,我们保证了发送有序。
RocketMQ的topic内的队列机制,可以保证存储满⾜FIFO(First Input First Output 简单说就是指先进先出),剩下的只需要消费者顺序消费即可。
RocketMQ仅保证顺序发送,顺序消费由消费者业务保证(多线程环境下需要唯一线程对一个消息队列按照有序消费)!!!

分布式事务(同时满⾜ACID特性)
分布式事务⼤概分为:

  • 2pc(两段式提交)
  • 3pc(三段式提交)
  • TCC(Try、Confirm、Cancel)
  • 最⼤努⼒通知
  • XA
  • 本地消息表(ebay研发出的)
  • 半消息/最终⼀致性(RocketMQ)

2pc(两段式提交)
在这里插入图片描述
2pc(两段式提交)可以说是分布式事务的最开始的样⼦了,像极了媒婆,就是通过消息中间件协调多个系统,在两个系统操作事务的时候都锁定资源但是不提交事务,等两者都准备好了,告诉消息中间件,然后再分别提交事务。
问题所在
如果A系统事务提交成功了,但是B系统在提交的时候⽹络波动或者各种原因提交失败了,其实还是会失败的

半消息/最终⼀致性:
在这里插入图片描述RocketMQ事务流程图
在这里插入图片描述

整个流程中,我们能保证是:

  • 业务主动⽅本地事务提交失败,业务被动⽅不会收到消息的投递。
  • 只要业务主动⽅本地事务执⾏成功,那么消息服务⼀定会投递消息给下游的业务被动⽅,并最终保证业务被动⽅⼀定能成功消费该消息(消费成功或失败,即最终⼀定会有⼀个最终态)

消息丢失
在这里插入图片描述
保障:
Producer发送机制、Broker的持久化机制,以及消费者的offSet机制来最大程度保证消息不易丢失在这里插入图片描述

RocketMQ

RocketMQ是⼀个纯Java、分布式、队列模型的开源消息中间件,前身是MetaQ,是阿⾥参考Kafka特点研发的⼀个队列模型的消息中间件,后开源给apache基⾦会成为了apache的顶级开源项⽬,具有⾼性能、⾼可靠、⾼实时、分布式特点。

架构组成
主要有四⼤核⼼组成部分:NameServer、Broker、Producer以及Consumer四部分。
在这里插入图片描述
NameServer:
主要负责对于源数据的管理,包括了对于Topic和路由信息的管理。

NameServer是⼀个功能⻬全的服务器,其⻆⾊类似Dubbo中的Zookeeper,但NameServer与Zookeeper相⽐更轻量。主要是因为每个NameServer节点互相之间是独⽴的,没有任何信息交互。
NameServer压⼒不会太⼤,平时主要开销是在维持⼼跳和提供Topic-Broker的关系数据。
但有⼀点需要注意,Broker向NameServer发⼼跳时, 会带上当前⾃⼰所负责的所有Topic信息,如果Topic个数太多(万级别),会导致⼀次⼼跳中,就Topic的数据就⼏⼗M,⽹络情况差的话, ⽹络传输失败,⼼跳失败,导致NameServer误认为Broker⼼跳失败。
NameServer 被设计成⼏乎⽆状态的,可以横向扩展,节点之间相互之间⽆通信,通过部署多台机器来标记⾃⼰是⼀个伪集群。
每个 Broker 在启动的时候会到 NameServer 注册,Producer 在发送消息前会根据 Topic 到NameServer 获取到 Broker 的路由信息,Consumer 也会定时获取 Topic 的路由信息。

Producer
消息⽣产者,负责产⽣消息,⼀般由业务系统负责产⽣消息。

Producer由⽤户进⾏分布式部署,消息由Producer通过多种负载均衡模式发送到Broker集群,发送低延时,⽀持快速失败。
RocketMQ 提供了三种⽅式发送消息:同步、异步和单向

  • 同步发送:同步发送指消息发送⽅发出数据后会在收到接收⽅发回响应之后才发下⼀个数据包。⼀般⽤于重要通知消息,例如重要通知邮件、营销短信。
  • 异步发送:异步发送指发送⽅发出数据后,不等接收⽅发回响应,接着发送下个数据包,⼀般⽤于可能链路耗时较⻓⽽对响应时间敏感的业务场景,例如⽤户视频上传后通知启动转码服务。
  • 单向发送:单向发送是指只负责发送消息⽽不等待服务器回应且没有回调函数触发,适⽤于某些耗时⾮常短但对可靠性要求并不⾼的场景,例如⽇志收集。

Broker
消息中转⻆⾊,负责存储消息,转发消息。

Broker是具体提供业务的服务器,单个Broker节点与所有的NameServer节点保持⻓连接及⼼跳,并会定时将Topic信息注册到NameServer,顺带⼀提底层的通信和连接都是基于Netty实现的。
Broker负责消息存储,以Topic为纬度⽀持轻量级的队列,单机可以⽀撑上万队列规模,⽀持消息推拉模型。
官⽹上有数据显示:具有上亿级消息堆积能⼒,同时可严格保证消息的有序性。

Consumer
消息消费者,负责消费消息,⼀般是后台系统负责异步消费。

Consumer也由⽤户部署,⽀持PUSH和PULL两种消费模式,⽀持集群消费和⼴播消息,提供实时的消息订阅机制。
Pull:拉取型消费者(Pull Consumer)主动从消息服务器拉取信息,只要批量拉取到消息,⽤户应⽤就会启动消费过程,所以 Pull 称为主动消费型。
Push:推送型消费者(Push Consumer)封装了消息的拉取、消费进度和其他的内部维护⼯作,将消息到达时执⾏的回调接⼝留给⽤户应⽤程序来实现。所以 Push 称为被动消费类型,但从实现上看还是从消息服务器中拉取消息,不同于 Pull 的是 Push ⾸先要注册消费监听器,当监听器处触发后才开始消费消息。

消息领域模型
在这里插入图片描述
Message

Message(消息)就是要传输的信息。

⼀条消息必须有⼀个主题(Topic),主题可以看做是你的信件要邮寄的地址。
⼀条消息也可以拥有⼀个可选的标签(Tag)和额处的键值对,它们可以⽤于设置⼀个业务 Key 并在Broker 上查找此消息以便在开发期间查找问题。

Topic
Topic(主题)可以看做消息的规类,它是消息的第⼀级类型。⽐如⼀个电商系统可以分为:交易消息、物流消息等,⼀条消息必须有⼀个 Topic 。
Topic 与⽣产者和消费者的关系⾮常松散,⼀个 Topic 可以有0个、1个、多个⽣产者向其发送消息,⼀个⽣产者也可以同时向不同的 Topic 发送消息。
⼀个 Topic 也可以被 0个、1个、多个消费者订阅。

Tag
Tag(标签)可以看作⼦主题,它是消息的第⼆级类型,⽤于为⽤户提供额外的灵活性。使⽤标签,同⼀业务模块不同⽬的的消息就可以⽤相同 Topic ⽽不同的 Tag 来标识。⽐如交易消息⼜可以分为:交易创建消息、交易完成消息等,⼀条消息可以没有 Tag 。
标签有助于保持您的代码⼲净和连贯,并且还可以为 RocketMQ 提供的查询系统提供帮助。

Group
分组,⼀个组可以订阅多个Topic。
分为ProducerGroup,ConsumerGroup,代表某⼀类的⽣产者和消费者,⼀般来说同⼀个服务可以作为
Group,同⼀个Group⼀般来说发送和消费的消息都是⼀样的

Queue
在Kafka中叫Partition,每个Queue内部是有序的,在RocketMQ中分为读和写两种队列,⼀般来说读写队列数量⼀致,如果不⼀致就会出现很多问题。

Message Queue
Message Queue(消息队列),主题被划分为⼀个或多个⼦主题,即消息队列。
⼀个 Topic 下可以设置多个消息队列,发送消息时执⾏该消息的 Topic ,RocketMQ 会轮询该 Topic 下的所有队列将消息发出去。
消息的物理管理单位。⼀个Topic下可以有多个Queue,Queue的引⼊使得消息的存储可以分布式集群化,具有了⽔平扩展能⼒。

Offset
在RocketMQ 中,所有消息队列都是持久化,⻓度⽆限的数据结构,所谓⻓度⽆限是指队列中的每个存储单元都是定⻓,访问其中的存储单元使⽤Offset 来访问,Offset 为 java long 类型,64 位,理论上在100年内不会溢出,所以认为是⻓度⽆限。
也可以认为 Message Queue 是⼀个⻓度⽆限的数组,Offset 就是下标

消息消费模式
消息消费模式有两种:Clustering(集群消费)和Broadcasting(⼴播消费)。
默认情况下就是集群消费,该模式下⼀个消费者集群共同消费⼀个主题的多个队列,⼀个队列只会被⼀个消费者消费,如果某个消费者挂掉,分组内其它消费者会接替挂掉的消费者继续消费。
⽽⼴播消费消息会发给消费者组中的每⼀个消费者进⾏消费。

Message Order
Message Order(消息顺序)有两种:Orderly(顺序消费)和Concurrently(并⾏消费)。
顺序消费表示消息消费的顺序同⽣产者为每个消息队列发送的顺序⼀致,所以如果正在处理全局顺序是强制性的场景,需要确保使⽤的主题只有⼀个消息队列。
并⾏消费不再保证消息顺序,消费的最⼤并⾏数量受每个消费者客户端指定的线程池限制。

⼀次完整的通信流程是怎样的?
Producer 与 NameServer集群中的其中⼀个节点(随机选择)建⽴⻓连接,定期从 NameServer 获取Topic 路由信息,并向提供 Topic 服务的 Broker Master 建⽴⻓连接,且定时向 Broker 发送⼼跳。
Producer 只能将消息发送到 Broker master,但是 Consumer 则不⼀样,它同时和提供 Topic 服务的Master 和 Slave建⽴⻓连接,既可以从 Broker Master 订阅消息,也可以从 Broker Slave 订阅消息。
在这里插入图片描述
NameService启动流程
第⼀步是初始化配置
第二步创建NamesrvController实例,并开启两个定时任务:

  • 每隔10s扫描⼀次Broker,移除处于不激活的Broker;
  • 每隔10s打印⼀次KV配置。

第三步注册钩⼦函数,启动服务器并监听Broker。
启动流程
在这里插入图片描述
小结
在这里插入图片描述

Producer
在这里插入图片描述
通过轮训,Producer轮训某个Topic下⾯的所有队列实现发送⽅的负载均衡
在这里插入图片描述
Broker
Broker在RocketMQ中是进⾏处理Producer发送消息请求,Consumer消费消息的请求,并且进⾏消息的持久化,以及HA策略和服务端过滤,就是集群中很重的⼯作都是交给了Broker进⾏处理。
Broker模块是通过BrokerStartup进⾏启动的,会实例化BrokerController,并且调⽤其初始化⽅法。

刷盘机制
RocketMQ的消息是存储到磁盘上的,这样既能保证断电后恢复, 又可以让存储的消息量超出内存的限制。RocketMQ为了提高性能,会尽可能地保证磁盘的顺序写。消息在通过Producer写入RocketMQ的时 候,有两种写磁盘方式,分布式同步刷盘和异步刷盘。
在这里插入图片描述

同步刷盘

在返回写成功状态时,消息已经被写入磁盘。具体流程是,消息写入内存的PAGECACHE后,立刻通知刷盘线程刷盘, 然后等待刷盘完成,刷盘线程执行完成后唤醒等待的线程,返回消息写 成功的状态。

异步刷盘

在返回写成功状态时,消息可能只是被写入了内存的PAGECACHE,写操作的返回快,吞吐量大;当内存里的消息量积累到一定程度时,统一触发写磁盘动作,快速写入

Consumer
在这里插入图片描述
Consumer是消息接受,那他怎么接收消息的呢?在这里插入图片描述
消费端会通过RebalanceService线程,10秒钟做⼀次基于Topic下的所有队列负载。

优缺点

RocketMQ优点
单机吞吐量:⼗万级
可⽤性:⾮常⾼,分布式架构
消息可靠性:经过参数优化配置,消息可以做到0丢失
功能⽀持:MQ功能较为完善,还是分布式的,扩展性好
⽀持10亿级别的消息堆积,不会因为堆积导致性能下降
源码是java,我们可以⾃⼰阅读源码,定制⾃⼰公司的MQ,可以掌控
天⽣为⾦融互联⽹领域⽽⽣,对于可靠性要求很⾼的场景,尤其是电商⾥⾯的订单扣款,以及业务
削峰,在⼤量交易涌⼊时,后端可能⽆法及时处理的情况
RoketMQ在稳定性上可能更值得信赖,这些业务场景在阿⾥双11已经经历了多次考验,如果你的
业务有上述并发场景,建议可以选择RocketMQ
RocketMQ缺点:
⽀持的客户端语⾔不多,⽬前是java及c++,其中c++不成熟
社区活跃度不是特别活跃那种
没有在 mq 核⼼中去实现JMS等接⼝,有些系统要迁移需要修改⼤量代码

消息去重
去重原则:使⽤业务端逻辑保持幂等性
幂等性:就是⽤户对于同⼀操作发起的⼀次请求或者多次请求的结果是⼀致的,不会因为多次点击⽽产⽣了副作⽤,数据库的结果都是唯⼀的,不可变的。
只要保持幂等性,不管来多少条重复消息,最后处理的结果都⼀样,需要业务端来实现。
去重策略:保证每条消息都有唯⼀编号(⽐如唯⼀流⽔号),且保证消息处理成功与去重表的⽇志同时出现。
建⽴⼀个消息表,拿到这个消息做数据库的insert操作。给这个消息做⼀个唯⼀主键(primary key)或者唯⼀约束,那么就算出现重复消费的情况,就会导致主键冲突,那么就不再处理这条消息
消息重复
消息领域有⼀个对消息投递的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对消息的刷盘提供了同步和异步的策略来满⾜我们的,当我们选择同步刷盘之后,如果刷盘超时会给返回FLUSH_DISK_TIMEOUT,如果是异步刷盘不会返回刷盘相关信息,选择同步刷盘可以尽最⼤程度满⾜我们的消息不会丢失。
除了存储有选择之后,我们的主从同步提供了同步和异步两种模式来进⾏复制,当然选择同步可以提升可⽤性,但是消息的发送RT时间会下降10%左右。
RocketMQ采⽤的是混合型的存储结构,即为Broker单个实例下所有的队列共⽤⼀个⽇志数据⽂件(即为CommitLog)来存储。
⽽Kafka采⽤的是独⽴型的存储结构,每个队列⼀个⽂件。
RocketMQ采⽤混合型存储结构的缺点在于,会存在较多的随机读操作,因此读的效率偏低。同时消费消息需要依赖ConsumeQueue,构建该逻辑消费队列需要⼀定开销。

RocketMQ 刷盘实现
Broker 在消息的存取时直接操作的是内存(内存映射⽂件),这可以提供系统的吞吐量,但是⽆法避免机器掉电时数据丢失,所以需要持久化到磁盘中。
刷盘的最终实现都是使⽤NIO中的 MappedByteBuffer.force() 将映射区的数据写⼊到磁盘,如果是同步刷盘的话,在Broker把消息写到CommitLog映射区后,就会等待写⼊完成。异步⽽⾔,只是唤醒对应的线程,不保证执⾏的时机,流程如图所示。
在这里插入图片描述
分布式事务:
Half Message(半消息)
是指暂不能被Consumer消费的消息。Producer 已经把消息成功发送到了 Broker 端,但此消息被标记为 暂不能投递 状态,处于该种状态下的消息称为半消息。需要 Producer对消息的 ⼆次确认 后,Consumer才能去消费它。

消息回查
由于⽹络闪段,⽣产者应⽤重启等原因。导致 Producer 端⼀直没有对 Half Message(半消息) 进⾏ ⼆次确认。这是Brock服务器会定时扫描 ⻓期处于半消息的消息 ,会主动询问 Producer端 该消息的最终状态(Commit或者Rollback),该消息即为 消息回查。
在这里插入图片描述

  1. A服务先发送个Half Message给Brock端,消息中携带 B服务 即将要+100元的信息。
  2. 当A服务知道Half Message发送成功后,那么开始第3步执⾏本地事务。
  3. 执⾏本地事务(会有三种情况1、执⾏成功。2、执⾏失败。3、⽹络等原因导致没有响应)
  4. 如果本地事务成功,那么Product像Brock服务器发送Commit,这样B服务就可以消费该message。
  5. 如果本地事务失败,那么Product像Brock服务器发送Rollback,那么就会直接删除上⾯这条半消息。
  6. 如果因为⽹络等原因迟迟没有返回失败还是成功,那么会执⾏RocketMQ的回调接⼝,来进⾏事务的回查。

消息过滤
Broker端消息过滤在Broker中,按照Consumer的要求做过滤,优点是减少了对于Consumer⽆⽤消息的⽹络传输。缺点是增加了Broker的负担,实现相对复杂。
Consumer端消息过滤 这种过滤⽅式可由应⽤完全⾃定义实现,但是缺点是很多⽆⽤的消息要传输到Consumer端。

Broker的Buffer问题
Broker的Buffer通常指的是Broker中⼀个队列的内存Buffer⼤⼩,这类Buffer通常⼤⼩有限。
另外,RocketMQ没有内存Buffer概念,RocketMQ的队列都是持久化磁盘,数据定期清除。
RocketMQ同其他MQ有⾮常显著的区别,RocketMQ的内存Buffer抽象成⼀个⽆限⻓度的队列,不管有多少数据进来都能装得下,这个⽆限是有前提的,Broker会定期删除过期的数据。
例如Broker只保存3天的消息,那么这个Buffer虽然⻓度⽆限,但是3天前的数据会被从队尾删除。

回溯消费
回溯消费是指Consumer已经消费成功的消息,由于业务上的需求需要重新消费,要⽀持此功能,Broker在向Consumer投递成功消息后,消息仍然需要保留。并且重新消费⼀般是按照时间维度。
例如由于Consumer系统故障,恢复后需要重新消费1⼩时前的数据,那么Broker要提供⼀种机制,可以按照时间维度来回退消费进度。
RocketMQ⽀持按照时间回溯消费,时间维度精确到毫秒,可以向前回溯,也可以向后回溯。

消息堆积
消息中间件的主要功能是异步解耦,还有个重要功能是挡住前端的数据洪峰,保证后端系统的稳定性,
这就要求消息中间件具有⼀定的消息堆积能⼒,消息堆积分以下两种情况:
消息堆积在内存Buffer,⼀旦超过内存Buffer,可以根据⼀定的丢弃策略来丢弃消息,如CORBA
Notification规范中描述。适合能容忍丢弃消息的业务,这种情况消息的堆积能⼒主要在于内存Buffer⼤⼩,⽽且消息堆积后,性能下降不会太⼤,因为内存中数据多少对于对外提供的访问能⼒影响有限。
消息堆积到持久化存储系统中,例如DB,KV存储,⽂件记录形式。 当消息不能在内存Cache命中时,要不可避免的访问磁盘,会产⽣⼤量读IO,读IO的吞吐量直接决定了消息堆积后的访问能⼒。

评估消息堆积能⼒主要有以下四点:
消息能堆积多少条,多少字节?即消息的堆积容量。
消息堆积后,发消息的吞吐量⼤⼩,是否会受堆积影响?
消息堆积后,正常消费的Consumer是否会受影响?
消息堆积后,访问堆积在磁盘的消息时,吞吐量有多⼤?

定时消息
定时消息是指消息发到Broker后,不能⽴刻被Consumer消费,要到特定的时间点或者等待特定的时间后才能被消费。
如果要⽀持任意的时间精度,在Broker层⾯,必须要做消息排序,如果再涉及到持久化,那么消息排序要不可避免的产⽣巨⼤性能开销。
RocketMQ⽀持定时消息,但是不⽀持任意时间精度,⽀持特定的level,例如定时5s,10s,1m等

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值