RocketMQ核心知识

roducer发消息,会先连
Transliteration
Roducer fā xiāoxī, huì xiān lián

目录

RocketMQ事务

RocketMQ集群

 集群特征

集群工作流程

消息的存储

顺序写与零拷贝

消息的存储结构

消息刷盘机制

同步刷盘:

异步刷盘:

MQ高可用与主从复制

高可用

主从复制

负载均衡 

Producer负载均衡

Consumer负载均衡

消息重试

消息重试机制分为顺序消息和无序消息

死信队列

消息重复消费

幂等

RocketMQ事务

事务消息流程:

角色:生产者,消费者,本地事务,经纪人Broker(也就是我们的MQ)

  1. 消息的生产者首先会发一个半消息给我们的Broker
  2. 然后Broker会返回一个ok状态给生产者
  3. 生产者这时就会去访问本地事务,本地事务会告诉生产者发送的信息是提交还是回滚
  4. 生产者会将从本地事务获取到的结果返回给Broker(提交还是回滚),还有一种是无反应
  5. 如果是无反应的,Broker会在向生产者索要结果
  6. 生产者就会在向本地事务索要结果
  7. 最后生产者在将结果返回给Broker
  8. 如果Broker接收到的是提交就将生产者发送的消息保存起来,供消费者消费
  9. 如果Broker接收到的是回滚就将生产者发送的消息删除掉,消费者就不能消费该消息了

注:5-6-7步骤称为消息的补偿过程

RocketMQ集群

单机:   

        使用单个Broker提供服务,一单Broker宕机,那么服务就不可用,也会造成一个数据的丢失

集群:

  • 使用多个Broker提供服务,解决单机情况下Broker一旦宕机就不可用的情况
  • Broker的作用是接收消息以及推送消息,也可以理解为读写操作
  • 在一个集群下,如果每个Broker都做读写操作的话,性能会比较低,所以会采用读写分离
  • 也就是说在集群下设置主机(master)与从机(slave),可以是多主多从的结构,master用于消息的写入,slave用于推送消息
  • 采用多主多从的结构,那么就需要考虑消息同步的问题,有两种方式
    • 同步:对比与异步性能略低,消息无延迟
    • 异步:对比与同步性能略高,消息有延迟

 集群特征

角色:producer(生产者)、consumer(消费者)、Broker(MQ)、NameServer(中控中心)

  • 所有的服务都会连接到NameServer中
  • 建立集群时,哪个Broker是master哪个是slave是根据Broker中的brokerId区分的。borkerId=0说明是master,否则都是slave
  • 而集群中又可以存在多主多从的结构,每个master和它的slave都可以看成是一个组,那么这就需要根据Broker中brokerName区分,如果brokerName的值是一样的就在一个组中
  • Broker集群中所有的Broker(maseter和slave)都会注册到NameServer中(NameServer也可以是一个集群,但是它们之间互不通信),并建立长连接。Broker和NameServer在进行数据同步的时候,Broker中有一个Topic是一个很重要的信息,需要同步到每一台NameServer中。Topic:消息的大分组,也就是生产者发送消息时分类存储的地方
  • 生产者发消息时(会提供一个Topic),首先会连接NameServer,根据Topic找对应的Broker,再从Broker中找到对应的Topic(Topic可以是很多个组,可以理解成是存放消息的管道,每个Topic是一个单独的管道,group则是存放这些管道的空间),然后就可以根据这些信息发送消息了。消费者与NameServer和Broker跟生成者是一样的

集群工作流程

  1. 先启动NameServer,开启监听,等待broker、producer和consumer连接
  2. broker启动,根据配置信息,连接到所有的NameServer,并保持一个长连接
  3. 如果broker中有数据,那么NameServer将会保存topic和broker的关系,因为最终会根据topic找到对应的broker
  4. producer发消息,会先连接NameServer,并建立长连接。(注意:并不是先连接Broker)
  5. producer发消息,存在两个情况:topic存在:由NameServer直接分配到对应的broker;topic不存在:由NameServer创建topic与broker的关系,并分配
  6. producer在broker中的topic选择一个小消息队列(从列表中选择)
  7. producer与broker建立长连接,用于发消息
  8. producer最终发送消息

消息的存储

Broker中为什么需要将消息存储起来?

答:防止Borker宕机,产生消息不可用的情况

消息可以存在数据库,但是消息的发送(存储速度)快慢很大程度上就取决于数据库的速度,它快则快,它慢则慢,所以会受到它的限制;而数据库最终存储数据的地方还是文件系统中,也就是硬盘中;所以可以选择将消息直接存入到文件系统中,这样就跨过了数据库,实现了存储。

所以随之而来的问题就是,怎么跨过数据库将消息存入文件系统中呢?

解决:采用消息刷盘机制进行数据存储

顺序写与零拷贝

顺序写:

        即使将消息直接存储到硬盘上,也还是会存在IO速度的问题,因为硬盘也分为机械硬盘和固态硬盘,这两者的IO速度差距是很大的,所以会采取固态硬盘进行存储

        而固态硬盘存储数据也分为随机写顺序写

  • 随机写:因为硬盘中会存在磁盘碎片,所以消息的存储可能就不是连续的,而是断续的存储
  • 顺序写:先占用一片空间,不允许其它业务使用,这样就能保证这一片空间是连续的,那么IO的速度将会大大提升(随机写(100KB/S);顺序写(600MB/S))

        所以RocketMQ采用的就是顺序写,它首先会在我们的磁盘空间开辟一个G的空间,这样需要写数据的时候就直接写在里面,大大提高了速度

零拷贝:

        数据的传输过程:

该过程总共经历了四次拷贝。网卡→内存数据不算拷贝

RocketMQ减少一次数据的拷贝,直接从内核态转为网络驱动内核,中间跳过了用户态;该过程就称为零拷贝技术

实现:java语言中使用MappedByteBuffer类实现了该技术

要求:预留存储空间,用户使用顺序写保存数据(1G存储空间起步)

消息的存储结构

也就是RocketMQ的结构

消息刷盘机制

将MQ的消息写入到磁盘的过程就叫刷盘,有两种方式:同步刷盘,异步刷盘

同步刷盘:

  1. 生产者发送消息给MQ,MQ接收到消息
  2. MQ就会挂起生产者发送消息的线程
  3. MQ将消息数据写入到内存中
  4. 内存数据写入磁盘中
  5. 数据写入磁盘完成后给MQ返回ok(SUCCESS)
  6. MQ接收到状态结果后,就会唤醒在挂起生产者发送消息的线程
  7. MQ就会将发送结果发给生产者

异步刷盘:

  1. 生产者发送消息给MQ,MQ接收到消息
  2. MQ将消息数据写入到内存中
  3. MQ返回发送结果给生产者

也就是说异步刷盘只有同步刷盘中的1,3,7步,因为将数据从内存写入到磁盘中是异步执行的,不在主流程中,也不需要将发送消息的线程挂起;

好处在于:生产者可以一直发消息,无需等待,当消息达到一定的量级在将数据进行一个异步的写入磁盘中

总结:

同步刷盘:安全性高,效率低,速度慢(使用于对数据安全要求较高的业务中)

异步刷盘:安全性低,效率高,速度快(用于对数据处理速度要求较高的业务中)

MQ高可用与主从复制

高可用

  • nameserve: 无状态+全服务注册,也可以搭建集群
  • 消息服务器(Broker):主从架构(双主双从)
  • 消息生产:生产者将相同的topic绑定到多个group组中,保障master挂掉后,其他的master仍可正常消息接收
  • 消息消费:RockerMQ自身会根据master承担消息读取的功能,当master繁忙时,自动切换由slave承担数据读取的工作

主从复制

也就是master数据同步到slave中的过程,分为同步复制和异步复制

同步复制:

  • master接收消息后,先复制到slave中,在返回结果给生产者
  • 优点:数据安全,不丢失数据,出现故障容易恢复
  • 缺点:影响数据的吞吐量,整体性能降低

异步复制:

  • master接收消息后,立即将操作成功的结果返回给生产者,当消息达到一定量后在异步复制到slave中
  • 优点:数据吞吐量大,操作延迟低,性能高
  • 缺点:数据不安全,会出现数据丢失的现象,一但master发生故障,那么从上次数据同步时间到出现故障时间之间的数据将会丢失

如何配置Broker是同步复制还是异步复制?

在下载的rocketmq文件的bin目录下有一个broker.conf配置文件,修改:

brokerRole = ASYNC_MASTER

ASYNC_MASTER:异步;前面不加A表示同步

负载均衡 

Producer负载均衡

场景:producer和broker都是集群

如果producer发送多个消息在分别对应borker集群中的broker 是同一个组(group),同一个队列(topic)的话,会将所有的消息顺序的发送broker对应的topic中

Consumer负载均衡

平均分配:将多个broker中的消息平均的分给consumer,如果平均是每个服务两个消息,那么会连续发送两个消息到每个consumer中

                  比如:有两个broker,broker1有1、2、3三个消息,broker2有4、5、6三个消息 有三个consumer都需要消费这些消息,那么会平均分配消息给consumer

  • consumer1就有消息1、2 
  • consumer2就有消息3、4 
  • consumer3就有消息5、6 

                   产生的问题:如果提供的broker的集群中有一个broker挂了,那么很有可能有些consumer会消费不到消息

循环平均分配:当broker集群提供消息时,会一条一条的将消息发给每一个consumer就避免了上面出现的问题

消息重试

什么是消息重试?

答:当broker推送消息给consumer后,consumer没有返回消费结果将会启动消息重试机制

消息重试机制分为顺序消息和无序消息

顺序消息:

当broker推送消息给consumer时,consumer如果没有返回消费结果,那么就会一直重复发送消息(1秒一次),直到consumer返回结果为止。(注意:如果consumer没有返回消息消费结果,消息是不会删除的)

这样虽然会保证我们的消息会被消费,但是会造成broke中消息的阻塞,前面的消息一直在发,后面的消息发不出去

无序消息:

  • 无序消息包括普通消息、定时消息、延时消息、事务消息
  • 无序消息重试仅适用于负载均衡(集群)模型下的消息消费,不适用于广播模式下的消费
  • 为保障无序消息的消费,MQ设定了合理的消息重试间隔时长

重试间隔时长

当MQ重试次数达到设置的默认最大次数后consumer还是没有返回结果,那么就会将消息放入MQ中的死信队列,那么消息就会变为死信

死信队列

死信队列特征:

  • 存放死信的对列,也就是未被消费的消息;它归属于组(group),而不是topic
  • 一个死信队列中可以包含同一个组下的多核Topic中的死信消息
  • 死信队列在没有死信的时候是没有的,只有在出现了死信,死信队列才会被创建出来

死信队列中消息特征:

  • 死信队列中的消息不会被主动消费,如果真想消费,可以根据消息id强制消费消息
  • 死信队列中的消息有效期为3天,达到后会被清除

消息重复消费

也就说broker推送消息给consumer,consumer消费完成后给broker返回成功结果时,broker因为某些原因没有收到consumer返回的结果,那么broker就会在发一次,那么就造成了消息的重复消费

消息重复消费的原因

使用消息幂等解决该问题

幂等

  • 对同一条消息,无论消费多少次,结果保持一致,称为消息幂等性
  • 解决方案
    • 使用业务id作为消息的key
    • 在消费消息时,客户端对key做判定,未使用过放行,使用过抛弃
  • 注意:messageId有RocketMQ产生,messageId并不具有唯一性,不能作用幂等判定条件,所以需要使用业务id
  • 常见的幂等方式实例:
    • 新增:不幂等        每次添加的数据返回的结果可以是不一致的 
    • 查询:幂等            必须保证同一个消息每次查询的结果是一致的
    • 删除:幂等            删除一条信息返回的结果必须是一致的
    • 修改:幂等            修改一条信息的状态为1,那么无论修改多少次,该状态还是要为1
    • 修改:不幂等        加钱,每次在原有的基础上加钱,那么每一次操作的结果都会不一样

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值