RocketMQ知识点整理

  • 一、消息队列
  • 二、RocketMQ简介
    • RocketMQ-组件
    • RocketMQ架构:
  • 三、 RocketMQ理解性问题整理
    • 1、使用消息中间件之前需要先了解“同步”调用、“异步”调用?
    • 2、消息重复消费问题(幂等性)
    • 3、如何保证消息的可靠性传输?或者说,如何处理消息丢失的问题?(漏消费)
    • 4、RocketMQ保证消息顺序
    • 5、消息积压如何处理?
    • 6、设计一个消息队列的思路?
    • 7、常用消息中间件区别,使用场景?
  • 参考:

一、消息队列

MQ(Message Queue)消息队列,是一种跨进程的通信方式,应用程序通过写入和检索出入队列的消息来通信,无需通过专用连接链接它们。MQ借助消息队列传递数据。

消息队列:
1、 解耦:消息生产者和消费者解耦,交互系统之间没有直接的调用关系,只通过消息传输,耦合度低。
2、 异步:消息进入队列后,不用立即处理,异步处理,加快系统响应速度。
3、 削峰限流:流量巨大的秒杀业务,通过MQ、减缓数据库的压力。

二、RocketMQ简介

RocketMQ是一款分布式、队列模型的消息中间件。
1、 支持集群模型、负载均衡、水平扩展能力。
2、 亿级别的消息堆积能力
3、 采用零拷贝、顺序写盘、随机读。
4、 丰富的API使用,支持同步、异步、顺序和事务型消息投递。
5、 代码优秀,底层通信框架采用Netty NIO框架
6、 NameServer代替Zookeeper(NameServer是更轻量级的网络路由的服务)
7、 强调集群无单点,可扩展,任意一点高可用
8、 消息失败重试机制、消息可查询

RocketMQ-组件

1、NameServer:主要负责对源数据管理,包括对于Topic和路由信息的管理。
NameServer是一个功能齐全的服务器,其角色类似Zookeeper,比zk更轻量级。
压力不会太大,主要开销在维持心跳和提供Topic-Broker的关系数据。
NameServer是几乎无状态的,可以横向扩展,节点之间相互无通信。

2、Broker:消息中转角色,负责存储消息,转发消息。
3、Producer消息生产者,业务系统负责产生消息。
4、Consumer:消息消费者,负责消费消息,一般是后台系统负责异步消费
5、Message:传输的信息
6、Topic:主题消息类型。
7、Tag:子主题,消息的第二类型。

RocketMQ架构:


一次完整的通信流程是怎样的?
Producer与NameServer集群中的其中一个节点(随机选择)建立长连接,定期从NameServer获取Topic路由信息,并向提供Topic服务的Broker Master建立长连接,且定时向Broker发送心跳。
Producer只能将消息发送到Broker master,但Consumer同时与Broker Master和BrokerSalve建立长连接。可以从master、和salve中订阅消息。

三、 RocketMQ理解性问题整理

1、使用消息中间件之前需要先了解“同步”调用、“异步”调用?

1、 同步调用意味着A、B、C三个系统,实现一个功能的调用链是:A调用B,B又调用C,A返回结果需要等待B,B要返回有需要C。
2、 引入MQ之后,原来的依赖关系转移了,从系统之间的依赖,变成系统都依赖MQ。就是A调用B,只需要向MQ发送一条消息,A就认为自己的工作完成了。B只需要从MQ中取得A发送的消息。实现A异步调用B。

由此MQ是让系统之间由同步到异步:实现1、提升性能;2、系统解耦;3、流量削峰。
1、 提升性能是指原来一个系统同步依赖每个系统,现在只需发送消息给MQ即可认为是任务完成。比如:A完成200ms,B完成20ms,请求需依赖A、B则同步情况下完成220ms,有了MQ都发给MQ即可。
2、 系统解耦,原来系统A、系统B强依赖,一旦一个系统出现问题会立刻影响到另个系统。现在只需要依赖MQ即可。
3、 流量削峰,高并发访问系统A,A需要调用数据库,那么系统瓶颈在数据库。(数据库系统复杂需要支持事务、锁、复杂SQL)同样的机器配置下,如果数据库可以抗每秒6000请求,MQ至少可以抗每秒几万请求。
引入MQ后,A系统依赖支持高并发的MQ,数据库也依赖MQ,可以以自己适合的速度读取消息。原来高并发流量在MQ被削峰了。整个系统性能由A决定而不是由B决定。

2、消息重复消费问题(幂等性)

面试题:如何保证消息不被重复消费?或者说,如何保证消息消费时的幂等性?

影响消息正常发送和消费的重要原因:网络的不确定性、人为的对服务端系统重启。

Consumer消费完消息后,应该发送COMSUME_SUCCESS确认消息通知broker,但因为网络原因,消息丢失。导致broker不知道consumer已消费过,又分发该消息给其他消费者。

补充:(RabbitMQ是发送ACK信息、Kafka有个offset的概念,Kafka 实际上有个 offset 的概念,就是每个消息写进去,都有一个 offset,代表消息的序号,然后 consumer 消费了数据之后,每隔一段时间(定时定期),会把自己消费过的消息的 offset 提交一下,表示“我已经消费过了,下次我要是重启啥的,你就让我继续从上次消费到的 offset 来继续消费吧“。)

解决方案
1、 由最后一道关卡数据库保证数据唯一性。也就是主键、唯一键保证,或者根据标准查验。
2、 写入redis,redis具有幂等性。
3、 生产者发送数据中带有UUID等唯一性凭据,消费者查询redis是否存在消费流水。

3、如何保证消息的可靠性传输?或者说,如何处理消息丢失的问题?(漏消费)

MQ有个基本原则,就是数据不能多一条,也不能少一条,不能多就是幂等性,不能少就是不能少消费,少发送消息。

RocketMQ消息丢失场景:
1、生产者投放消息给MQ时,通信异常消息丢失。
2、RocketMQ持久化消息过程中,没来得及异步刷盘RocketMq宕机消息丢失,消息写入磁盘但是没备份消息丢失。
3、消费者异步消费消息,但是异步过程中消费者宕机。

关于第二步详细说明:
①RocketMQ为了减少磁盘的IO,会先将消息写入到os cache中,而不是直接写入到磁盘中,消费者从os cache中获取消息类似于直接从内存中获取消息,速度更快,过一段时间会由os线程异步的将消息刷入磁盘中,此时才算真正完成了消息的持久化。在这个过程中,如果消息还没有完成异步刷盘,RocketMQ中的Broker宕机的话,就会导致消息丢失
②如果消息已经被刷入了磁盘中,但是数据没有做任何备份,一旦磁盘损坏,那么消息也会丢失

解决方案:(如何保证消息零丢失)

1、 场景1中保证传输过程中消息不丢失,直接开启RocketMq的事务型消息sendMessageInTransaction保证消息的投放成功。启用消息监听器,监听消费者返回的事务状态。
2、 场景3中让消费者开启,自身消息监听器registerMessageListener,消费成功返回CONSUME_SUCCESS。
3、 场景2中,os cache的异步刷盘改用同步刷盘,这一步需要修改Broker的配置文件,将flushDiskType改为SYNC_FLUSH同步刷盘策略,默认的是ASYNC_FLUSH异步刷盘。一旦同步刷盘返回成功,那么就一定保证消息已经持久化到磁盘中了。
对于硬盘损坏,我们保证磁盘锁坏不会丢失数据,对RocketMq采取主从架构,集群部署。Leader中的数据在多个Follower中都有备份,防止单点故障。

上面的一整套方案可以保证RocketMQ的消息零丢失。但是性能和吞吐量大大下降。
1、 事务型消息传输,比普通消息传输多出很多步骤,消耗性能。
2、 同步刷盘相比异步刷盘,一个存储在内存,一个存储在磁盘,速度差距大
3、 主从架构,需要主从复制。
4、 消费时无法异步消费只能等待消费完成再通知RocketMQ。

参考:https://blog.csdn.net/LO_YUN/article/details/103949317

4、RocketMQ保证消息顺序

这是使用MQ的时候必问话题,第一看你了不了解顺序这个事?第二看看你有没有办法保证消息是有顺序的?这是生产系统中常见的问题。

如果三个消息是对数据的增加、修改、删除。如果消息执行顺序搞错了,本来这个数据应该本删除,但是最后却被保留下来,导致数据不一致。

RabbitMQ中消息从queue中出来被不同的消费者拉取消费,导致顺序不一致。RocketMq者RabbitMQ类似,不过是在同一Topic不同的MessageQueue中,被不同的消费者消费导致的问题。

1、RabbitMq问题:

2、RocketMq问题:

解决方案:
RabbitMq是先划分多个queue,一个queue对应一个消费者,然后同一key的消息进入同一个queue,然后被相同的消费者消费。(不展开说)

RocketMq:只要将有序的消息按照顺序都放入同一个MessageQueue中,最后就能被同一个消费者顺序消费了。
在代码层面,我们可以在消息投放时,根据特定条件(相同的key,比如相同的订单号),将这类消息投放到相同的MessageQueue中。(相同的msg的id,可以通过orderId对length取模得到)

SendResult sendResult = producer.send(msg, new MessageQueueSelector() {@Overridepublic MessageQueue select(List<MessageQueue> mqs, Message msg, Object arg) {Integer id = (Integer) arg;int index = id % mqs.size();return mqs.get(index);}
}, orderId);

还有一个问题,就是消费者在消费顺序消息失败了怎么办?
RocketMq默认是返回ConsumeConcurrentlyStatus.RECOSUME_LATER。表示将该消息放入重试队列中稍后重试。这显然违背了顺序执行条件。我们可以修改默认返回,返回一个ConsumeOrderlyStatus.SUSPEND_CURRENT_QUEUE_A_MOMENT让当前队列等一会再消费,只有前面的消息消费结束,才轮到后面消息。【或者使用事务型消息,执行丢失、错误直接回滚,重新来一遍。这样的话吞吐量、性能就会下降】

@Override
public ConsumeOrderlyStatus consumeMessage(List<MessageExt> msgs, ConsumeOrderlyContext context) {    //业务代码       if (消费成功) {  return ConsumeOrderlyStatus.SUCCESS;} else {return ConsumeOrderlyStatus.SUSPEND_CURRENT_QUEUE_A_MOMENT;}
}

5、消息积压如何处理?

如何解决消息队列的延时以及过期失效问题?消息队列满了以后该怎么处理?有几百万消息持续积压几小时,说说怎么解决?

1、后台定时任务每隔72小时,删除旧的没有使用过的消息信息

2、根据不同的业务实现不同的丢弃任务,选择不同的策略淘汰任务,例如FIFO/LRU等

3、(1)临时紧急扩容,新建一个topic,临时建立好原来10倍的MessageQueue数量,(2)写一个临时的消费数据的consumer程序,采用多线程消费,消费后不做耗时处理,部署到服务器端。(3)快速消费完积压数据之后,恢复到原先部署的架构。(推荐)

MQ中的消息过期失效了?

采用消息批量重导策略。
使用RocketMQ的回溯消费机制,回溯消费是指Consumer已经消费成功的消息,由于业务上的需求需要重新消费,要支持此功能,Broker在向Consumer投递成功消息后,消息仍然需要保留。并且重新消费一般是按照时间维度。

例如由于Consumer系统故障,恢复后需要重新消费1小时前的数据,那么Broker要提供一种机制,可以按照时间维度来回退消费进度。

RocketMQ支持按照时间回溯消费,时间维度精确到毫秒,可以向前回溯,也可以向后回溯。

6、设计一个消息队列的思路?

其实聊到这个问题,一般面试官要考察两块:

你有没有对某一个消息队列做过较为深入的原理的了解,或者从整体了解把握住一个消息队列的架构原理。
看看你的设计能力,给你一个常见的系统,就是消息队列系统,看看你能不能从全局把握一下整体架构设计,给出一些关键点出来。
说实话,问类似问题的时候,大部分人基本都会蒙,因为平时从来没有思考过类似的问题,大多数人就是平时埋头用,从来不去思考背后的一些东西。类似的问题,比如,如果让你来设计一个 Spring 框架你会怎么做?如果让你来设计一个 Dubbo 框架你会怎么做?如果让你来设计一个 MyBatis 框架你会怎么做?

设计解答:
1、首先这个 mq 得支持可伸缩性吧,就是需要的时候快速扩容,就可以增加吞吐量和容量,那怎么搞?设计个分布式的系统呗,参照一下 kafka 的设计理念,broker -> topic -> partition,每个 partition 放一个机器,就存一部分数据。如果现在资源不够了,简单啊,给 topic 增加 partition,然后做数据迁移,增加机器,不就可以存放更多数据,提供更高的吞吐量了。(RocketMQ扩展成nameServer、broker集群的设计)
2、持久化机制,可以异步刷盘还可以同步刷盘。持久化可以顺序写,这样就没有磁盘随机读写的寻址开销,磁盘顺序读写的性能是很高的,这就是 kafka 的思路。
3、可用性。MQ可以有多个leader和follower,多副本保证broker的高可用。
4、支持0丢失。支持事务型消息、支持broker主从架构、支持磁盘备份。

7、常用消息中间件区别,使用场景?

提高性能、解耦系统、流量削峰。
参考:https://github.com/doocs/advanced-java/blob/master/docs/high-concurrency/why-mq.md

提一嘴提高性能:

耗时:(用户感受到的耗时)3+300+450+200ms = 953ms

耗时:(用户感觉到的耗时)3+5=8ms

消息队列应用带来的缺点:
1、 系统的复杂度高。
添加了MQ进来,使得系统所需要考虑的问题多了,保证消息没有重复消费?怎么处理消息丢失的情况?怎么保证消息传递的顺序性?
2、 系统的可用性降低。
如果MQ不是集群,分布式部署,那么MQ宕机全部的系统都不可以工作。

3、 一致性问题。
异步更新数据库时,用户看到处理成功,但是在B、C、D下游系统写入时,有一个出错了,保证数据一致性成为问题。

Kafka、ActiveMQ、RabbitMQ、RocketMQ 有什么优缺点?

参考:

https://blog.csdn.net/lo_yun/category_9480949.html
https://github.com/doocs/advanced-java/blob/master/docs/high-concurrency/why-mq.md
https://blog.csdn.net/dingshuo168/article/details/102970988

RocketMQ知识点整理相关推荐

  1. RocketMQ 知识点整理

    文章目录 什么是RMQ?架构介绍 消息持久化 异步刷盘 RocketMQ为什么速度快 延迟消息 事务消息 过滤消息 有序消息 批量消息 消息轨迹(msg trace) 消费重试 死信队列 广播消息 o ...

  2. Java进阶3 - 易错知识点整理(待更新)

    Java进阶3 - 易错知识点整理(待更新) 该章节是Java进阶2- 易错知识点整理的续篇: 在前一章节中介绍了 ORM框架,中间件相关的面试题,而在该章节中主要记录关于项目部署中间件,监控与性能优 ...

  3. 面试题引出的知识点整理

    1.自旋锁&可重复锁&公平锁&共享锁&分段锁你都知道吗? 2.无锁&偏向锁&轻量级锁&重量级锁如何膨胀升级? 3.Lock底层AQS实现与Syn ...

  4. C语言考研复试知识点整理

    C语言考研复试知识点整理 1.由float x=3e-6,y=3e-6;不能得到x= =y的逻辑值为真. 解析:float类型的变量只能进行>或<运算,不能进行==运算 2.自增和自减运算 ...

  5. 【Android 面试基础知识点整理】

    针对Android面试中常见的一些知识点整理,Max 仅仅是个搬运工.感谢本文中引用文章的各位作者,给大家分享了这么多优秀文章.对于当中的解析,是原作者个人见解,有错误和不准确的地方,也请大家积极指正 ...

  6. mysql 存储引擎 面试_搞定PHP面试 - MySQL基础知识点整理 - 存储引擎

    MySQL基础知识点整理 - 存储引擎 0. 查看 MySQL 支持的存储引擎 可以在 mysql 客户端中,使用 show engines; 命令可以查看MySQL支持的引擎: mysql> ...

  7. mysql 全面知识点_Mysql知识点整理

    1.存储引擎区别 MyISAM:不支持事物.仅支持表级锁.支持B+树索引 MEMORY:不支持事物.仅支持表级锁.支持B+树和HASH索引 InnoDB:支持事物.支持行级锁.支持B+树索引 2.锁机 ...

  8. 04741计算机网络原理知识点,04741计算机网络原理知识点整理.doc

    04741计算机网络原理知识点整理 1.计算机网络大发展 计算机网络从20世纪70年代开始发展,他的演变可以概括为 面向终端的计算机网络.计算机-计算机网络.开放式标准化网络以及因特网广泛应用和高速网 ...

  9. python基础知识整理-python入门基础知识点整理-20171214

    一.知识点整理 1.python2与python3的区别: (1)宏观比对 python2 源码不标准,较为混乱,并且重复的代码很多. python3 源码统一了标准,同时也去除了重复代码. (2)编 ...

最新文章

  1. 【python编程导论】我想和你探讨下如何去写好程序
  2. python学不会的表情包-小学生绞尽脑汁也学不会的python(反射)
  3. hdu4635(最多加多少边,使得有向图不是强连通图)
  4. [Yii Framework] 数据库查询
  5. 《java入门第一季》之类String类小案例
  6. Python之Pandas库
  7. elementui如何在input 框中搜索_【挑战自学Python编程】第八天:while循环以及input()函数...
  8. oracle查询创建用户,Oracle创建设置查询权限用户
  9. android优化大师下载最新版,安卓优化大师(正式版)
  10. 【狂神说Java】Docker最新超详细版教程通俗易懂笔记
  11. 有隐藏分区如何激活win7旗舰版
  12. 五星大饭店剧情,五星大饭店在线观看
  13. 手机储存卡数据怎么恢复
  14. java clh_【Java并发编程实战】----- AQS(四):CLH同步队列
  15. Elang之ETS系列函数功能与用法详解
  16. 软件架构设计原则-里氏替换原则
  17. K-Means对红酒数据进行聚类||python
  18. C# 窗口关闭再次确认及取消
  19. 抽象类与接口的区别,以及使用依据
  20. 用Wcat隐藏你的程序窗口

热门文章

  1. cv2.error: opencv(4.4.0)_【从零学习OpenCV 4】图像金字塔
  2. 【前端必备】七、页面性能优化
  3. 解开Future的神秘面纱之任务执行
  4. NOIP模拟 color(DP)
  5. Linux CA证书与https讲解
  6. k上升段,对于排列问题的处理
  7. bzoj 3238: [Ahoi2013]差异
  8. 创新数字音频处理技术带来消费电子产品差异化用户体验(转)
  9. 设计模式六大原则你都知道吗?
  10. 基于Xilinx Spartan-7 FPGA实现SMC接口