MQ学习笔记(三) MQ高频面试题

Kafka

1、谈谈你对Kafka的理解?(高频)

优势特点

高吞吐量、低延迟(kafka每秒可以处理几十万条消息,它的延迟最低只有几毫秒,每个topic可以分多个 partition, consumer group 对partition进行consume操作)

可扩展性(kafka集群支持热扩展)

持久性、可靠性(消息被持久化到本地磁盘,并且支持数据备份防止数据丢失)

容错性(允许集群中节点失败(若副本数量为n,则允许n-1个节点失败))

高并发(支持数千个客户端同时读写)

架构组件

三个基本组件(Producer、Broker、Consumer) Zookeeper(负责Kafka集群元数据的管理;Broker节点信息、Topic信息、Topic的Partition信息等)

高可用

分区副本机制 ISR机制(replica.lag.time.max.ms设置数据同步时间差 默认10s、Leader选举机制 ==> 引出Controller选举) ACK机制(取值-1 ==> 引出幂等性;跨分区、跨会话 ==> 引出Kafka事务)

高并发

生产者Producer(RecordBatch-消息批量写入) 服务器Broker(分区+副本) 消费者Consumer(消费者组)

高性能

Reactor多路复用模型(Kafka的SocketServer基Java NIO开发,采用了Reactor的模式) 采用批量消息发送(减少了请求、提高了吞吐量) 磁盘顺序写 & Page Cache(先写到页缓存、操作系统再择机将缓存中的数据刷入磁盘;读数据也是先从缓存中 读、没有再去磁盘读) 零拷贝技术(跳过两次拷贝数据的步骤、减少拷贝带来的CPU开销、减少用户态内核态的上下文切换次数、优 化了数据传输性能)

2、Kafka 如何保证数据可靠性和数据一致性?(高频)

数据可靠性

Kafka可靠性设计

Producter往Broker发送消息(消息确认机制 ACK[0、1、-1])

Topic分区副本(1个Leader,n个Follower,读写在Leader,Follower到Leader上的复制数据)Leader选举(若Leader挂了,ISR中第一个副本会成为Leader,不会影响服务提供)

应用时的设置

Producter(API设置:acks=all、producer.type=sync) Topic(API设置:replication.factor>=3、min.insync.replicas>=2) Broker(API设置:unclean.leader.election.enable=false)

数据一致性

主要讲Kafka主从同步的过程

Kafka的主从同步设计能够保证:不管是之前挂掉的Leader,还是新选举的Leader,Consumer都能读到一样的 数据;

Kafka主从同步中设计了一个HW(最高水位),水位以上的消息才可以被Consumer消费,水位是一种遵循木桶 原理的设计;

举例说明:假设,HW在消息3的位置,一个消费者从当前 Leader(副本0) 读取并处理了消息4,这个时候 Leader 挂掉了,选举了副本1为新的 Leader,这时候另一个消费者再去从新的 Leader 读取消息,发现这个消 息其实并不存在,就会导致数据不一致性问题,HW取最小LEO值(所有节点中最小同步位置),解决了数据一 致性问题;

还可以提一提API相关配置(通过配置 replica.lag.time.max.ms 参数,可以指定副本复制消息的最大延迟时间, 这个决定了副本是否处于ISR中)

3、说说ACK机制?主从同步?ISR机制?(高频)

ACK应答机制

配置项 equest.required.acks 有三个值:0、1(默认值)、-1(all)

0:生产者不会等待 broker 的 ack,这个延迟最低但是存储的保证最弱当 server 挂掉的时候就会丢数据;

1:服务端会等待 ack 值 leader 副本确认接收到消息后发送 ack 但是如果 leader挂掉后他不确保是否复制完成 新 leader 也会导致数据丢失;

-1(all):服务端会等所有的 follower 的副本数据落盘后才会收到 leader 发出的ack,这样数据不会丢失;

主从同步

阐述副本概念、Leader和Follower角色,主要讲Follower到Leader同步数据的过程HW(水位)等概念

 Kafka的复制机制既不是完全的同步复制,也不是单纯的异步复制;完全同步复制要求All Alive Follower都复制 完,这条消息才会被认为Commit,这种复制方式极大的影响了吞吐率;而异步复制方式下,Follower以异步的 方式从Leader复制数据,数据只要被Leader写入Log就被认为已经Commit,这种情况下,如果leader挂掉,会 丢失数据;Kafka使用ISR的方式很好的均衡了确保数据不丢失和高吞吐;Follower可以批量的从Leader复制数 据,而且Leader充分利用磁盘顺序读以及零拷贝机制(sendFile()调用),这样极大的提高同步复制数据的性 能,内部批量写磁盘,大幅减少了Follower与Leader的消息量差;

ISR

可以先介绍一下相关概念:ISR、OSR、AR

AR(Assigned Replicas,所有副本,AR=ISR+OSR)

ISR(In-Sync Replicas,同步副本队列,所有和主副本保持同步的副本集合)

OSR(Out-of-Sync Replicas,滞后副本队列,所有和主副本同步滞后的副本集合)

再讲ISR的意义和存储

ISR机制是Kafka的同步策略,主要目的在于提高分区容错性(主要解决当acks=-1时,某个Follower挂掉, 影响Kafka运行的问题)

ISR是由Leader维护,它是一个Set集合、存储的节点是动态调整的(Kafka的副本管理器会启动过期检测 的定时任务),若某个Follower从Leader同步数据有延迟、超过相应的阈值就会将其剔除出 ISR;存入 OSR列表,OSR中的内容若恢复同步设定的阈值,又会回到ISR队列中;新加入的Follower会先存放到 OSR中,同步达到阈值转入ISR中;

4、Kafka如何保障数据不丢失?(高频)

核心就是两个点:

生产者发送的消息确保其在服务器Broker上落盘;

消费者能够消费到服务器Broker上的消息;

解决方案:

生产者端

重试次数(retries值)设置大一些 acks=-1(所有副本完成同步)

服务器端

确保存储数据的高可靠性(分区副本) 节点的高可靠性(ISR)

消费者端

禁用Offset自动提交(enable.auto.commit=false),消费者处理完消息之后再手动提交Offset(防止消费 者端拉到消息后,还走完业务处理流程,出现异常,但Offset已提交的情况)

5、Kafka怎样确保消息的顺序消费?(高频)

Kafka只保证单Partition消息有序、并不能保证多分区消息的有序性,所以要确保消息顺序消费,要么使用单分区的 Topic(不过单分区Topic会影响吞吐量、数据量大还会造成消息堆积)、要么在Topic多分区情况下,让一类业务消息 写到Topic的一个分区中(指定消息写入的分区或Partition Key值),最稳妥的做法是:一个生产者一个单分区Topic 一个消费者;

那为什么架构设计者,不把它设计成多分区有序呢?首先要明白分区的目的是为了实现横向扩展、提高并发访问的性 能;如果Kafka要保证多个Partition有序,不仅Broker端保存的数据要有序,消费时也要按序消费;假设1分区堵了, 为了有序性,那2分区及其后续的3分区、N分区也只能停下来等待、不能被消费,这种情况下,Kafka就退化成了单 一队列,毫无并发性可言,极大降低系统性能,这违背了Partition设计的初衷; 当然也有一些,特殊场景:要使用多分区、有要保证消息有序,这个时候也可以考虑采用一些业务手段来处理,不过 多分区情况下Kafka本身就无法严格保证消费顺序,所以说也是尽人事听天命;

解决方案:可以根据产生消息对象内部的时间(即生产消息时写入的EventTime),然后通过watermark来做批量消 费,保证窗口有序,但是难免会有特殊情况导致消息到达并不准时,对于超出太多时间的消息,可以收集到数据库进 行一些祢补的处理;

6.Kafka幂等性实现?

先讲Kafka幂等性的两个重要概念:ProducerID、SequenceNumber

ProducerID:每创建一个新的生产者,就会分配一个唯一的ProducerID,用于标识它; SequenceNumber:生产者发送数据到每个Topic的Partition都对应一个从0开始递增的SN值,用于标识消 息;

再讲幂等性的缺陷(只能单会话、单分区)以及Kafka的解决方案(Kafka事务处理流程)

最后介绍API的配置设定就行了(enable.idempotence=ture)

MQ通用问题

1、你对MQ的理解?(高频)

概念(MQ全称是Message Queue,消息队列,主要作用是:在分布式系统间实现异步通信)

主要组成

生产者端(创建和发送业务消息)

服务端端(存储和转发消息)

消费者端(消费消息,根据拿到的消息做对应的业务处理)

元数据管理中心(Kafka使用ZK、RocketMQ使用NS) 其他组件也可以提一提

应用场景

流量消峰(对突然产生的大量请求进行缓冲,先将大量请求转化为消息存入MQ,由MQ对请求进行分发、 降低服务器压力)

应用解耦(订单系统 ==> MQ ==> 物理系统、库存系统、物流系统)

异步处理(如果没有实时性要求,可以使用MQ将原本串行模块优化为异步执行,如:登录时的验证码发 送、订单支付后的通知)

常见MQ产品

ActiveMQ(老古董、早期单体应用的选择)

RabbitMQ(原生语言erLang的并发优势)

Kafka(海量数据、高吞吐量)

RocketMQ(要求消息可靠性、支持分布式事务)

Pulsar(下一代云原生分布式消息流支持)

2、MQ产生消息积压,你怎样解决?(高频)

积压原因

生产者端生产过快:访问量、数据量激增、如:热点事件、热门活动等,导致大量的数据涌入业务系统,有可 能导致消息积压;

消费者端消费不动:Consumer程序故障、无消费动作,也会导致大量消息未被消费、造成消息的积压;

Kafka数据倾斜问题:Producer 写入数据时候设置的key 发生数据倾斜,导致过度数据写入少量Partition;

解决方法

提升生产者的吞吐量(调整生产者发送消息的缓冲区大小[写满会阻塞 做压测]、压缩格式[lz4]、调整批次大小 [默认16kb]);

增加更多的Consumer,增加消费能力,从而处理积压数据;

如果发现是数据倾斜问题,可以在Producer端对key做均匀处理,确保分区间数据均衡;

如何排查

大部分消息队列都内置或支持三方的监控工具,通过监控数据,很容易确定是哪种原因(这个一般是运维的工作)

如果监控到:单位时间发送的消息暴增

比如:大促或者抢购活动,可以通过增加消费端的消费者来提升消费能力; 如果资源比较紧张,没法对消费端进行扩容,那就将系统降级,关闭一些不太重要的业务,减少发送方发送的 数据量,最低限度让系统能正常运转,维持一些重要业务的服务;

如果监控是:消费变慢了

检查你的消费实例,分析一下是什么原因导致消费变慢; 优先检查一下日志是否有大量的消费错误,如果没有错误的话,可以通过打印堆栈信息,看一下你的消费线程 是不是卡在什么地方不动了,比如触发了死锁或者卡在等待某些资源上了

如果监控发现:发送消息、消费消息的速度和平时没什么差别

检查消费端,看是不是某条消息消费失败,导致一条消息反复消费,这种情况也会拖慢整个系统的消费速度;

线上运行项目MQ组件出现消息积压

思路:临时扩容,加快消费数据的速度

具体操作(参考):

1. 先修复当前Consumer出现的问题,确保其恢复消费,修复后将当前Consumer都停掉;

2. 临时建立好比原先10倍或者20倍的Queue数量(Kakfa新建一个Topic,Partition是原来的10倍);

3. 然后写一个临时消费消息的Consumer程序,把这个程序部署上、去消费积压的消息,消费之后不做耗时 处理,直接均匀轮询写入刚刚临时建好分10数量的Queue中;

4. 紧接着征用10倍的机器来部署Consumer,每一批Consumer消费一个临时Queue的消息(这种做法相当于 临时将Queue资源和Consumer资源扩大10倍,以正常速度的10倍来消费消息);

5. 等快速消费完了之后,恢复原来的部署架构,重新用原来的Consumer来消费消息(在第一步时已经修复 好了)。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值