消息队列面试连环问:如何保证消息不丢失?处理重复消息?消息有序性?消息堆积处理?(上)

简介: 消息队列面试连环问:如何保证消息不丢失?处理重复消息?消息有序性?消息堆积处理?(上)

大家好,我是 yes。

最近我一直扎在消息队列实现细节之中无法自拔,已经写了 3 篇Kafka源码分析,还剩很多没肝完。之前还存着RocketMQ源码分析还没整理。今儿暂时先跳出来盘一盘大方向上的消息队列有哪些核心注意点。

核心点有很多,为了更贴合实际场景,我从常见的面试问题入手:

  • 如何保证消息不丢失?
  • 如果处理重复消息?
  • 如何保证消息的有序性?
  • 如果处理消息堆积?

当然在剖析这几个问题之前需要简单的介绍下什么是消息队列,消息队列常见的一些基本术语和概念

接下来进入正文。


什么是消息队列


来看看维基百科怎么说的,顺带学学英语这波不亏:

In computer science, message queues and mailboxes are software-engineering components typically used for inter-process communication (IPC), or for inter-thread communication within the same process. They use a queue for messaging – the passing of control or of content. Group communication systems provide similar kinds of functionality.

翻译一下:在计算机科学领域,消息队列和邮箱都是软件工程组件,通常用于进程间或同一进程内的线程通信。它们通过队列来传递消息-传递控制信息或内容,群组通信系统提供类似的功能。

简单的概括下上面的定义:消息队列就是一个使用队列来通信的组件

上面的定义没有错,但就现在而言我们日常所说的消息队列常常指代的是消息中间件,它的存在不仅仅只是为了通信这个问题。


为什么需要消息队列


从本质上来说是因为互联网的快速发展,业务不断扩张,促使技术架构需要不断的演进。

从以前的单体架构到现在的微服务架构,成百上千的服务之间相互调用和依赖。从互联网初期一个服务器上有 100 个在线用户已经很了不得,到现在坐拥10亿日活的微信。我们需要有一个「东西」来解耦服务之间的关系、控制资源合理合时的使用以及缓冲流量洪峰等等。

消息队列就应运而生了。它常用来实现:异步处理、服务解耦、流量控制


异步处理

随着公司的发展你可能会发现你项目的请求链路越来越长,例如刚开始的电商项目,可以就是粗暴的扣库存、下单。慢慢地又加上积分服务、短信服务等。这一路同步调用下来客户可能等急了,这时候就是消息队列登场的好时机。


调用链路长、响应就慢了,并且相对于扣库存和下单,积分和短信没必要这么的 "及时"。因此只需要在下单结束那个流程,扔个消息到消息队列中就可以直接返回响应了。而且积分服务和短信服务可以并行的消费这条消息。


可以看出消息队列可以减少请求的等待,还能让服务异步并发处理,提升系统总体性能

image.png


服务解耦

上面我们说到加了积分服务和短信服务,这时候可能又要来个营销服务,之后领导又说想做个大数据,又来个数据分析服务等等。

可以发现订单的下游系统在不断的扩充,为了迎合这些下游系统订单服务需要经常地修改,任何一个下游系统接口的变更可能都会影响到订单服务,这订单服务组可疯了,真 ·「核心」项目组


image.png

image.png

所以一般会选用消息队列来解决系统之间耦合的问题,订单服务把订单相关消息塞到消息队列中,下游系统谁要谁就订阅这个主题。这样订单服务就解放啦!


image.png


流量控制

想必大家都听过「削峰填谷」,后端服务相对而言都是比较「弱」的,因为业务较重,处理时间较长。像一些例如秒杀活动爆发式流量打过来可能就顶不住了。因此需要引入一个中间件来做缓冲,消息队列再适合不过了。


网关的请求先放入消息队列中,后端服务尽自己最大能力去消息队列中消费请求。超时的请求可以直接返回错误。


当然还有一些服务特别是某些后台任务,不需要及时地响应,并且业务处理复杂且流程长,那么过来的请求先放入消息队列中,后端服务按照自己的节奏处理。这也是很 nice 的。


上面两种情况分别对应着生产者生产过快和消费者消费过慢两种情况,消息队列都能在其中发挥很好的缓冲效果。



image.png


注意

引入消息队列固然有以上的好处,但是多引入一个中间件系统的稳定性就下降一层,运维的难度抬高一层。因此要权衡利弊系统是演进的


消息队列基本概念


消息队列有两种模型:队列模型发布/订阅模型


队列模型

生产者往某个队列里面发送消息,一个队列可以存储多个生产者的消息,一个队列也可以有多个消费者, 但是消费者之间是竞争关系,即每条消息只能被一个消费者消费。


image.png


发布/订阅模型

为了解决一条消息能被多个消费者消费的问题,发布/订阅模型就来了。该模型是将消息发往一个Topic即主题中,所有订阅了这个 Topic 的订阅者都能消费这条消息。

其实可以这么理解,发布/订阅模型等于我们都加入了一个群聊中,我发一条消息,加入了这个群聊的人都能收到这条消息。 那么队列模型就是一对一聊天,我发给你的消息,只能在你的聊天窗口弹出,是不可能弹出到别人的聊天窗口中的。


讲到这有人说,那我一对一聊天对每个人都发同样的消息不就也实现了一条消息被多个人消费了嘛。


是的,通过多队列全量存储相同的消息,即数据的冗余可以实现一条消息被多个消费者消费。RabbitMQ 就是采用队列模型,通过 Exchange 模块来将消息发送至多个队列,解决一条消息需要被多个消费者消费问题。


这里还能看到假设群聊里除我之外只有一个人,那么此时的发布/订阅模型和队列模型其实就一样了。


image.png


小结一下

队列模型每条消息只能被一个消费者消费,而发布/订阅模型就是为让一条消息可以被多个消费者消费而生的,当然队列模型也可以通过消息全量存储至多个队列来解决一条消息被多个消费者消费问题,但是会有数据的冗余。

发布/订阅模型兼容队列模型,即只有一个消费者的情况下和队列模型基本一致。

RabbitMQ 采用队列模型,RocketMQKafka 采用发布/订阅模型。

接下来的内容都基于发布/订阅模型


常用术语

一般我们称发送消息方为生产者 Producer,接受消费消息方为消费者Consumer,消息队列服务端为Broker

消息从Producer发往BrokerBroker将消息存储至本地,然后ConsumerBroker拉取消息,或者Broker推送消息至Consumer,最后消费。


image.png


为了提高并发度,往往发布/订阅模型还会引入队列或者分区的概念。即消息是发往一个主题下的某个队列或者某个分区中。RocketMQ中叫队列,Kafka叫分区,本质一样。

例如某个主题下有 5 个队列,那么这个主题的并发度就提高为 5 ,同时可以有 5 个消费者并行消费该主题的消息。一般可以采用轮询或者 key hash 取余等策略来将同一个主题的消息分配到不同的队列中。


与之对应的消费者一般都有组的概念 Consumer Group, 即消费者都是属于某个消费组的。一条消息会发往多个订阅了这个主题的消费组。


假设现在有两个消费组分别是Group 1Group 2,它们都订阅了Topic-a。此时有一条消息发往Topic-a,那么这两个消费组都能接收到这条消息。

然后这条消息实际是写入Topic某个队列中,消费组中的某个消费者对应消费一个队列的消息。


在物理上除了副本拷贝之外,一条消息在Broker中只会有一份,每个消费组会有自己的offset即消费点位来标识消费到的位置。在消费点位之前的消息表明已经消费过了。当然这个offset是队列级别的。每个消费组都会维护订阅的Topic下的每个队列的offset

来个图看看应该就很清晰了。


image.png


基本上熟悉了消息队列常见的术语和一些概念之后,咱们再来看看消息队列常见的核心面试点。


相关实践学习
RocketMQ一站式入门使用
从源码编译、部署broker、部署namesrv,使用java客户端首发消息等一站式入门RocketMQ。
消息队列 MNS 入门课程
1、消息队列MNS简介 本节课介绍消息队列的MNS的基础概念 2、消息队列MNS特性 本节课介绍消息队列的MNS的主要特性 3、MNS的最佳实践及场景应用 本节课介绍消息队列的MNS的最佳实践及场景应用案例 4、手把手系列:消息队列MNS实操讲 本节课介绍消息队列的MNS的实际操作演示 5、动手实验:基于MNS,0基础轻松构建 Web Client 本节课带您一起基于MNS,0基础轻松构建 Web Client
相关文章
|
1月前
|
消息中间件 关系型数据库 MySQL
2020年最新面试真题(1):为什么使用消息队列?
2020年最新面试真题(1):为什么使用消息队列?
31 2
|
3月前
|
安全 Java 编译器
【面试问题】说说原子性、可见性、有序性?
【1月更文挑战第27天】【面试问题】说说原子性、可见性、有序性?
|
7月前
|
存储 缓存 运维
JVM面试连环炮
JVM面试连环炮
70 0
|
4天前
|
设计模式 搜索推荐 Java
面试官不按套路出牌,上来就让聊一聊Java中的迭代器(Iterator ),夺命连环问,怎么办?
面试官不按套路出牌,上来就让聊一聊Java中的迭代器(Iterator ),夺命连环问,怎么办?
12 0
|
2月前
|
消息中间件 存储 监控
美团面试:Kafka如何处理百万级消息队列?
美团面试:Kafka如何处理百万级消息队列?
135 1
|
3月前
|
消息中间件 缓存 运维
【面试问题】如何解决消息队列的延时以及过期失效问题?
【1月更文挑战第27天】【面试问题】如何解决消息队列的延时以及过期失效问题?
|
3月前
|
消息中间件 存储 缓存
【面试问题】MQ 如何保证消息的顺序性?
【1月更文挑战第27天】【面试问题】MQ 如何保证消息的顺序性?
|
4月前
|
算法 安全 调度
[操作系统] 面试宝典之~死锁连环系列
[操作系统] 面试宝典之~死锁连环系列
|
5月前
|
消息中间件 存储 NoSQL
MQ消息队列篇:三大MQ产品的必备面试种子题
MQ(Message Queue)作为一种用于实现异步通信的技术,具有重要的作用和应用场景。在面试过程中,MQ相关的问题经常被问到,因此了解MQ的用途和设计原则是必不可少的。本文总结了MQ的常见面试题,包括MQ的作用、产品选型、消息不丢失的保证、消息消费的幂等性、消息顺序的保证、消息的高效读写、分布式事务的最终一致性等方面。通过深入理解这些问题,可以更好地理解MQ的应用和设计,为面试和实际应用提供参考。
101 0