01 面试官心理分析
如果有人问到你MQ的知识,高可用是必问的。因为 MQ 会导致系统可用性降低,所以只要你用了MQ,接下来问的一些要点肯定就是围绕着MQ的那些缺点怎么来解决了。
要是你傻乎乎的就干用了一个MQ,各种问题从来没考虑过,那你就杯具了,面试官对你的感觉就是,只会简单使用一些技术,没任何思考,马上对你的印象就不太好了。这样的同学招进来要是做个20k薪资以内的普通小弟还凑合,要是做薪资20k+的高工,那就惨了,让你设计个系统,里面肯定一堆坑,出了事故公司受损失,团队一起背锅。
02 面试题剖析:如何保证 “消息队列” 的高可用?
这个问题这么问是很好的,因为不能问你Kafka高可用性怎么保证?ActiveMQ 高可用性怎么保证?一个面试官要是这么问就显得很没水平,人家可能用的就是RabbitMQ,没用过Kafka,你上来问人家Kafka干什么?这不是摆明了刁难人么...
所以有水平的面试官,问的是MQ的高可用性怎么保证?这样就是你用过哪个MQ,你就说说你对哪个MQ的高可用性的理解。
题目来源:《Java高级程序员面试指南--消息队列篇》,从“面试官心理分析”到“面试题剖析”,一步一步深入解析!如需参考这份面试指南→请看原件【点击获取】
2.1 RabbitMQ的高可用性
RabbitMQ是比较有代表性的,因为是基于主从(非分布式〉做高可用性的,我们就以RabbitMQ为例子讲解第一种 MQ的高可用性怎么实现。
RabbitMQ有三种模式:单机模式、普通集群模式、镜像集群模式。
单机模式
单机模式,就是 Demo级别的,一般就是你本地启动了玩玩儿的。
普通集群模式(无高可用性)
普通集群模式,意思就是在多台机器上启动多个 RabbitMQ实例,每个机器启动一个。你创建的queue,只会放在一个RabbitMQ实例上,但是每个实例都同步queue 的元数据(元数据可以认为是 queue 的一些配置信息,通过元数据,可以找到queue 所在实例)。你消费的时候,实际上如果连接到了另外一个实例,那么那个实例会从queue所在实例上拉取数据过来。
这种方式确实很麻烦,也不怎么好,没做到所谓的分布式,就是个普通的集群。因为这导致你要么消费者每次随机连接一个实例然后拉取数据,要么固定连接那个queue所在实例消费数据,前者有数据拉取的开销,后者导致单实例性能瓶颈。
而且如果那个放 queue 的实例宕机了,会导致接下来其他实例就无法从那个实例拉取,如果你开启了消息持久化,让 RabbitMQ落地存储消息的话,消息不一定会丢,得等这个实例恢复了,然后才可以继续从这个queue拉取数据。
所以这个事儿就比较尴尬了,这就没有什么所谓的高可用性,这方案主要是提高吞吐量的,就是说让集群中多个节点来服务某个queue的读写操作。
镜像集群模式(高可用性)
这种模式,才是所谓的RabbitNQ的高可用模式。跟普通集群模式不一样的是,在镜像集群模式下,你创建的 queue,无论是元数据还是 queue 里的消息都会存在于多个实例上,就是说,每个RabbitMQ节点都有这个queue 的一个完整镜像,包含 queue 的全部数据的意思。然后每次你写消息到 queue 的时候,都会自动把消息同步到多个实例的queue 上。
那么如何开启这个镜像集群模式呢﹖其实很简单,RabbitMQ有很好的管理控制台,就是在后台新增一个策略,这个策略是镜像集群模式的策略,指定的时候是可以要求数据同步到所有节点的,也可以要求同步到指定数量的节点,再次创建queue 的时候,应用这个策略,就会自动将数据同步到其他的节点上去了。
这样的话,好处在于,你任何一个机器宕机了,没事儿,其它机器(节点)还包含了这个queue 的完整数据,别的 consumer都可以到其它节点上去消费数据。坏处在于,第一,这个性能开销也太大了吧,消息需要同步到所有机器上,导致网络带宽压力和消耗很重!第二,这么玩儿,不是分布式的,就没有扩展性可言了,如果某个queue 负载很重,你加机器,新增的机器也包含了这个queue 的所有数据,并没有办法线性扩展你的 queue。你想,如果这个queue 的数据量很大,大到这个机器上的容量无法容纳了,此时该怎么办呢?
2.2 Kafka的高可用性
Kafka一个最基本的架构认识:由多个broker组成,每个 broker 是一个节点;你创建一个topic,这个topic可以划分为多个 partition,每个partition可以存在于不同的 broker 上,每个partition 就放一部分数据。
这就是天然的分布式消息队列,就是说一个topic 的数据,是分散放在多个机器上的,每个机器就放一部分数据。
实际上 RabbmitMQ之类的,并不是分布式消息队列,它就是传统的消息队列,只不过提供了一些集群、HA(High Availability,高可用性)的机制而已,因为无论怎么玩儿,RabbitMQ一个queue 的数据都是放在一个节点里的,镜像集群下,也是每个节点都放这个queue 的完整数据。
Kafka0.8以前,是没有HA 机制的,就是任何一个 broker 宕机了,那个broker 上的 partition 就废了,没法写也没法读,没有什么高可用性可言。
比如说,我们假设创建了一个topic,指定其 partition数量是3个,分别在三台机器上。但是,如果第二台机器宕机了,会导致这个topic 的 1/3的数据就丢了,因此这个是做不到高可用的。
Kafka 0.8 以后,提供了HA 机制,就是 replica(复制品)副本机制。每个 partition 的数据都会同步到其它机器上,形成自己的多个replica副本。所有 replica 会选举一个leader出来,那么生产和消费都跟这个leader打交道,然后其他replica 就是 follower。写的时候,leader会负责把数据同步到所有 follower 上去,读的时候就直接读leader 上的数据即可。只能读写leader?很简单,要是你可以随意读写每个follower,那么就要care数据一致性的问题,系统复杂度太高,很容易出问题。Kafka 均匀地将一个partition 的所有 replica 分布在不同的机器上,这样才可以提高容错性。
这么搞,就有所谓的高可用性了,因为如果某个broker宕机了,没事儿,那个broker上面的 partition在其他机器上都有副本的。如果这个宕机的 broker 上面有某个 partition 的 leader,那么此时会从follower中重新选举一个新的 leader出来,大家继续读写那个新的 leader即可。这就有所谓的高可用性了。
写数据的时候,生产者就写leader,然后leader 将数据落地写本地磁盘,接着其他 follower自己主动从leader来 pull数据。一旦所有 follower同步好数据了,就会发送 ack给 leader,leader收到所有 follower的 ack 之后,就会返回写成功的消息给生产者。(当然,这只是其中一种模式,还可以适当调整这个行为)
消费的时候,只会从leader去读,但是只有当一个消息已经被所有 follower 都同步成功返回 ack 的时候,这个消息才会被消费者读到。
看到这里,相信你大致明白了Kafka是如何保证高可用机制的了,对吧?不至于一无所知,现场还能给面试官画画图。要是遇上面试官确实是Kafka高手,深挖了问,那你只能说不好意思,太深入的你没研究过。
03 此外关于kafka面试
整理了44道面试官最爱问的kafka面试题,从基础-进阶-高级,分类整理,先看题目...
这里给出了全部的题目,关于答案解析,内容偏多(我将其整理成31页的PDF文档),篇幅有限,只截图展现部分答案解析,如需参考完整的kafka44问解析文档原件→【点击获取】
kafka基础面试题(17道)
-
Kafka的用途有哪些?使用场景如何?
-
Kafka中的ISR、AR又代表什么?ISR的伸缩又指什么
-
Kafka中的HW、LEO、LSO、LW等分别代表什么?
-
Kafka中是怎么体现消息顺序性的?
-
Kafka中的分区器、序列化器、拦截器是否了解?它们之间的处理顺序是什么?
-
Kafka生产者客户端的整体结构是什么样子的?
-
Kafka生产者客户端中使用了几个线程来处理?分别是什么?
-
Kafka的旧版Scala的消费者客户端的设计有什么缺陷?
-
“消费组中的消费者个数如果超过topic的分区,那么就会有消费者消费不到数据”这句话是否正确?如果正确,那么有没有什么hack的手段?
-
有哪些情形会造成重复消费?
-
哪些情景下会造成消息漏消费?
-
KafkaConsumer是非线程安全的,那么怎么样实现多线程消费?
-
简述消费者与消费组之间的关系
-
当你使用kafka-topics.sh创建(删除)了一个topic之后,Kafka背后会执行什么逻辑?
-
topic的分区数可不可以增加?如果可以怎么增加?如果不可以,那又是为什么?
-
topic的分区数可不可以减少?如果可以怎么减少?如果不可以,那又是为什么?
-
创建topic时如何选择合适的分区数?
kafka进阶面试题(15道)
-
Kafka目前有哪些内部topic,它们都有什么特征?各自的作用又是什么?
-
优先副本是什么?它有什么特殊的作用?
-
Kafka有哪几处地方有分区分配的概念?简述大致的过程及原理
-
简述Kafka的日志目录结构
-
Kafka中有哪些索引文件?
-
如果我指定了一个offset,Kafka怎么查找到对应的消息?
-
如果我指定了一个timestamp,Kafka怎么查找到对应的消息?
-
聊一聊你对Kafka的Log Retention的理解
-
聊一聊你对Kafka的Log Compaction的理解
-
聊一聊你对Kafka底层存储的理解
-
聊一聊Kafka的延时操作的原理
-
聊一聊Kafka控制器的作用
-
Kafka的旧版Scala的消费者客户端的设计有什么缺陷?
-
消费再均衡的原理是什么?(提示:消费者协调器和消费组协调器)
-
Kafka中的幂等是怎么实现的?
kafka高级面试题(12道)
-
Kafka中的事务是怎么实现的?
-
失效副本是指什么?有哪些应对措施?
-
多副本下,各个副本中的HW和LEO的演变过程
-
Kafka在可靠性方面做了哪些改进?(HW, LeaderEpoch)
-
为什么Kafka不支持读写分离?
-
Kafka中的延迟队列怎么实现
-
Kafka中怎么实现死信队列和重试队列?
-
Kafka中怎么做消息审计?
-
Kafka中怎么做消息轨迹?
-
怎么计算Lag?(注意read_uncommitted和read_committed状态下的不同)
-
Kafka有哪些指标需要着重关注?
-
Kafka的哪些设计让它有如此高的性能?
04 最后RabbitMQ专题
RabbitMQ面试
整理了24道RabbitMQ面试问题(附答案)
-
RabbitMQ 中的 broker 是指什么?cluster 又是指什么?
-
什么是元数据?元数据分为哪些类型?包括哪些内容?与 cluster 相关的元数据有哪些?元数据是如何保存的?元数据在 cluster 中是如何分布的?
-
RAM node 和 disk node 的区别?
-
RabbitMQ 上的一个 queue 中存放的 message 是否有数量限制?
-
RabbitMQ 概念里的 channel、exchange 和 queue 这些东东是逻辑概念,还是对应着进程实体?这些东东分别起什么作用?
-
vhost 是什么?起什么作用?
-
在单 node 系统和多 node 构成的 cluster 系统中声明 queue、exchange ,以及进行 binding 会有什么不同?
-
8. 客户端连接到 cluster 中的任意 node 上是否都能正常工作?
-
若 cluster 中拥有某个 queue 的 owner node 失效了,且该 queue 被声明具有durable 属性,是否能够成功从其他 node 上重新声明该 queue ?
-
cluster 中 node 的失效会对 consumer 产生什么影响?若是在 cluster 中创建了mirrored queue ,这时 node 失效会对 consumer 产生什么影响?
-
能够在地理上分开的不同数据中心使用 RabbitMQ cluster 么?
-
为什么 heavy RPC 的使用场景下不建议采用 disk node ?
-
向不存在的 exchange 发 publish 消息会发生什么?向不存在的 queue 执行consume 动作会发生什么?
-
routing_key 和 binding_key 的最大长度是多少?
-
RabbitMQ 允许发送的 message 最大可达多大?
-
什么情况下 producer 不主动创建 queue 是安全的?
-
“dead letter”queue 的用途?
-
为什么说保证 message 被可靠持久化的条件是 queue 和 exchange 具有durable 属性,同时 message 具有 persistent 属性才行?
-
什么情况下会出现 blackholed 问题?
-
如何防止出现 blackholed 问题?
-
Consumer Cancellation Notification 机制用于什么场景?
-
Basic.Reject 的用法是什么?
-
为什么不应该对所有的 message 都使用持久化机制?
-
RabbitMQ 中的 cluster、mirrored queue,以及 warrens 机制分别用于解决什么问题?存在哪些问题?
RabbitMQ架构大纲(学习路线图)
这是手绘版的(xmind文件),原件无法上传,这里用的图片...
但无论是面试文档pdf还是这路线图xmind,若你需要参考学习→请看原件【点击获取】