kafka面试篇

消息队列的作用:异步、削峰填谷、解耦

高可用,几乎所有相关的开源软件都支持,满足大多数的应用场景,尤其是大数据和流计算领域,

  • kafka高效,可伸缩,消息持久化。支持分区、副本和容错。
  • 对批处理和异步处理做了大量的设计,因此Kafka可以得到非常高的性能。

  • 每秒处理几十万异步消息,如果开启了压缩,可以达到每秒处理2000w消息的级别。
  • 但是由于是异步的和批处理的,延迟也会高。

  • Producer API:允许应用程序将记录流发布到一个或多个Kafka主题。

  • Consumer API:允许应用程序订阅一个或多个主题并处理为其生成的记录流。

  • Streams API:允许应用程序充当流处理器,将输入流转换为输出流。

kafka的数据单元称为消息,可以将消息看成是数据库里的一个“数据行”或一条“记录”。

批次

为了提高效率,消息被分批次写入kafka,提高吞吐量却加大了响应时间。

主题Topic

通过主题进行分类,类似数据库中的表。

分区Partition

Topic可以被分成若干分区分布于kafka集群中,方便扩容

单个分区内是有序的,partition设置为1,才可以保证全局有序。

副本Replicas

每个主题被分为若干个分区,每个分区有多个副本。

生产者Producer

生产者在默认情况下把消息均衡地分布到主题的所有分区上:

  • 直接指定消息的分区
  • 根据消息的key散列取模得出分区
  • 轮询指定分区

消费者Comsumer

消费者通过偏移量来区分已经读过的消息,从而消费消息。将每个分区最后读取的消息偏移量保存到Zookeeper 或Kafka上,如果消费者关闭或重启,它的读取状态不会丢失。

消费组ComsumerGroup

消费组保证每个分区只能被一个消费者使用,避免重复消费。如果群组内一个消费者失效,消费组的其他消费者可以接管失效消费者的工作再平衡,重新分区。

节点Broker

连接生产者和消费者,单个broker可以轻松处理数千个分区以及每秒百万级的消息量。

  • broker接收来自生产者的消息,为消息设置偏移量,并提交消息到磁盘保存。
  • broker为消费者提供服务,响应读取分区的请求,返回已经提交到磁盘上的消息。

集群

每个分区都有一个首领,当分区被分配给多个broker时,会通过首领进行分区复制。 

生产者offset

消息写入的时候,每一个分区都有一个offset,即每个分区的最新最大的offset。

消费者offset

不用消息组中的消费者可以针对一个分区存储不同的offset,互不影响。

LogSegment

  • 一个分区由多个LogSegment组成,
  • 一个LogSegment由.log /.index / .timeindex组成

  • .log追加时顺序写入的,文件名是以文件中第一条message的offset来命名的
  • .index进行日志删除时和数据查找的时候可以快速定位。
  • .timeStamp则根据时间戳查找对应的偏移量。

kafka的优点

  • 高吞吐量:单机每秒处理几十上百万的消息量。即使存储了TB级消息,也保持稳定的性能。

    • 零拷贝:减少内核态到用户态的拷贝,磁盘通过sendfile实现DMA 拷贝Socket buffer
    • 顺序读写:充分利用磁盘顺序读写的超高性能

    • 页缓存mmap,将磁盘文件映射到内存, 用户通过修改内存就能修改磁盘文件。

  • 高性能:单节点支持上千个客户端,并保证零停机和零数据丢失。
  • 持久化:将消息持久化到磁盘,通过将数据持久化到硬盘以及replication防止数据丢失。
  • 分布式系统:易扩展。所有的组件均为分布式的,无需停机即可扩展机器。

  • 可靠性 : Kafka是分布式,分区,复制和容错的。

kafka的应用场景

  • 日志收集:用Kafka可以收集各种服务的Log,通过大数据平台进行处理;

  • 消息系统:解耦生产者和消费者,缓存消费等;
  • 用户活动跟踪:Kafka经常被用来记录Web用户或者App用户的各种活动,如浏览网页、搜索、点击等活动,这些活动信息被各个服务器发布到kafka的topic中,然后消费者通过订阅这些Topic来做运营数据的实时的监控分析,也可以保存到数据库;

生产消费基本流程

1.Producer创建时,会创建一个sender线程并设置为守护线程

2.生产的消息先经过拦截器-->序列化器-->分区器,然后将消息缓存在缓冲区。

3.批次发送的条件是:缓冲区数据大小达到batch.size或者linger.ms达到上限。

4.批次发送后,发往制定分区,然后分区落盘到broker。

  • acks=0只需要将消息放到缓冲区,就认为消息已经发送完成。
  • acks=1表示消息只需要写入主分区即可。在该情形下,如果主分区收到消息确认之后就会宕机了,而副本分区还没来得及同步该消息,则该消息丢失。
  • acks=all(默认)首领分区会等待所有的ISR副本分区确认记录。该处理保证了只要有一个isr副本分区存活,消息就不会丢失。

5.如果生产者配置了retrires参数大于0并且未收到确认,那么客户端会对该消息进行重试。

6.落盘到broker成功,赶回生产元数据给生产者。

Leader选举

  • kafka会在zookeeper上针对每个topic维护一个称为ISR(in-sync-replica)的集合;
  • 当集合中副本都跟leader中的副本同步了之后,kafka才会认为消息已提交;
  • 只有这些跟Leader保持同步的Follower才应该被选作新的Leader;

  • 假设某个topic有N+1个副本,kafka可以容忍N个服务器不可用,冗余度较低。

  • 如果ISR中的副本都丢失了,则:

    • 可以等待ISR中的副本任何一个恢复,接着对外提供服务,需要时间等待。
    • 从OSR中选择出一个副本做Leader副本,此时会造成数据丢失;

副本消息同步

 首先,Follower发送FETCH请求给leader。接着Leader 会读取底层日志文件中的消息数据,再更新它内存中的Follwer副本的LEO值,更新为FETCH请求中的 fetchOffset值。最后,尝试更新分区高水位值。Follower接收到FETCH响应之后,会把消息写入到底层日志,接着更新 LEO 和 HW 值。

相关概念:LEO和HW        

  • LEO:即日志末端位移(log end offset),记录了该副本日志中下一条消息的位移值,如果LEO=10,那么表示该副本保存了10条消息,位移值范围是【0,9】
  • HW:水位值HW(high watermark)即已备份位移。对于同一个副本对象而言,其HW值不会大于LEO值。小于等于HW值的所有消息都被认为是“已备份”的(replicated)。

Rebalance

  • 组成员数量发生变化
  • 订阅主题数量发生变化
  • 订阅主题的分区数发生变化

     leader选举完成后,当以上三种情况发生时,leader根据配置的RangeAssignor算法开始分配消费方案,即哪个consumer负责消费哪些topic的哪些partiiton。一旦完成分配,leader会将这个方案封装进SyncGroup请求中发给coordinator,非leader也会发SyncGroup请求,只是内容为空。coordinator接收到分配方案之后会把方案塞进SyncGroup的response中发给各个consumer。这样组内的所有成员就都知道自己应该消费哪些分区了。

分区分配算法RangeAssignor

  • 原理是按照消费者总数和分区总数进行整除运算平均分配给所有的消费者;
  • 订阅topic的消费者按照名称的字典序排序,分均分配,剩下的字典序从前往后分配;

如何查看偏移量为23的消息?

   通过查询跳跃表ConcurrentSkipListMap,定位到在00000000000000000000.index ,通过二分法在偏移量索引文件中找到不大于 23 的最大索引项,即offset 20 那栏,然后从日志分段文件中的物理位置为320开始顺序查找偏移量为23的消息。

切分文件

  • 大小分片 当前日志分段文件的大小超过了 broker 端参数 log.segment.bytes 配置的值;

  • 时间分片 当前日志分段中消息的最大时间戳与系统的时间戳的差值大于log.roll.ms配置的值;

  • 索引分片 偏移量或时间戳索引文件大小达到broker端 log.index.size.max.bytes配置的值;

  • 偏移分片 追加的消息的偏移量与当前日志分段的偏移量之间的差值大于 Integer.MAX_VALUE;

幂等性

保证在消息重发的时候,消费者不会重复处理。即使在消费者收到重复消息的时候,重复处理,也要保证最终结果的一致性。所谓幂等性,数学概念就是:f(f(x)) = f(x) 

幂等性如何实现?

添加唯一ID,类似于数据库的主键,用于唯一标记一个消息。

ProducerID:#在每个新的Producer初始化时,会被分配一个唯一的PIDSequenceNumber:
#对于每个PID发送数据的每个Topic都对应一个从0开始单调递增的SN值

Leader选举

1.使用Zookeeper的分布式锁选举控制器,并在节点加入集群或退出集群时通知控制器。

2.控制器负责在节点加入或离开集群时进行分区leader选举。

3.控制器使用epoch忽略小的纪元来避免脑裂:两个节点同时认为自己是当前的控制器。

可用性

  • 创建Topic的时候可以指定 --replication-factor 3 ,表示不超过broker的副本数

  • 只有Leader是负责读写的节点,Follower定期地到Leader上Pull数据。
  • ISR是Leader负责维护的与其保持同步的Replica列表,即当前活跃的副本列表。如果一个Follower落后太多,Leader会将它从ISR中移除。选举时优先从ISR中挑选Follower。
  • 设置acks=all。Leader收到了ISR中所有Replica的 ACK,才向Producer发送ACK。

面试题

1)线上问题rebalance

因为集群架构变动导致的消费组内重平衡,如果kafka集群内节点较多,比如数百个,那重平衡可能会耗时导致数分钟到数小时,此时kafka基本处于不可用状态,对kafka的TPS影响极大。

产生的原因:

  • 组成员数量发生变化

  • 订阅主题数量发生变化

  • 订阅主题的分区数发生变化

     组成员崩溃和组成员主动离开是两个不同的场景。因为在崩溃时成员并不会主动的告知coordinator,coordinator有可能需要一个完整的session.timeout周期(心跳周期)才能检测到这种崩溃,这必然会造成consumer的滞后。主动离开是主动发起rebalance,而崩溃是被动发起rebalance。

解决方案:

加大超时时间 session.timout.ms=6s
加大心跳频率 heartbeat.interval.ms=2s
增长推送间隔 max.poll.interval.ms=t+1 minutes

2)ZooKeeper 的作用

目前,Kafka 使用 ZooKeeper 存放集群元数据、成员管理、Controller 选举,以及其他一些管理类任务。之后,等 KIP-500 提案完成后,Kafka 将完全不再依赖于 ZooKeeper。

  • 存放元数据是指主题分区的所有数据都保存在ZooKeeper,其他“人”都要与它保持对齐。
  • 成员管理是指Broker节点的注册,注销以及属性变更等。
  • Controller 选举是指选举集群 Controller,包括但不限于主题删除,参数配置等。

一言以蔽之:KIP-500 ,是使用社区自研的基于 Raft 的共识算法,实现 Controller 自选举。

同样是存储元数据,这几年基于Raft算法的etcd认可度越来越高。

3)Replica副本的作用

kafka只有Leader副本才能对外提供读写服务响应 Clients 端的请求。Follower副本只是采取拉(PULL)的方式,被动地同步Leader副本中的数据,并且在 Leader 副本所在的 Broker 宕机后,随时准备应聘Leader 副本。(Follower --> Leader)

  • 自 Kafka 2.4 版本开始,社区可以通过配置参数,允许 Follower 副本有限度地提供读服务。

  • 之前确保一致性的主要手段是高水位机制, 但高水位值无法保证 Leader 连续变更场景下的数据一致性,因此,社区引入了 Leader Epoch 机制,来修复高水位值的弊端。

4)为什么不支持读写分离?

  • 自 Kafka 2.4 之后,Kafka 提供了有限度的读写分离。

  • 场景不适用。读写分离适用于读负载很大,而写操作相对不频繁的场景。
  • 同步机制。Kafka 采用 PULL 方式实现 Follower 的同步,同时复制延迟较大。

5)如何防止重复消费

  • 代码层面每次消费需提交offset;
  • 通过Mysql的唯一键约束,结合Redis查看id是否被消费,存Redis可以直接使用set方法;
  • 量大且允许误判的情况下,使用布隆过滤器也可以。

6)如何保证数据不会丢失

  • 生产者生产消息可以通过comfirm配置ack=all解决;(生产端)

  • Broker节点同步过程中leader宕机可以通过配置ISR副本+重试解决;(Broker)
  • 消费者丢失可以关闭自动提交offset功能,系统处理完成时提交offset;(消费端)

7)如何保证顺序消费

  • 设置单topic,单partiiton,单consumer,吞吐量底,不推荐;
  • 如只需保证单key有序,为每个key单独申请内存queue,每个线程分别消费一个内存queue 即可,这样就能保证单key(例如用户id、活动id)顺序性。

8)线上如何解决积压消费

  • 修复consumer,使其具备消费能力,并且扩容N台;
  • 写一个分发的程序,将Topic均匀分发到临时Topic中;
  • 同时启N台消费者consumer,消费不同的临时Topic

9)如何避免消息积压

  • 提高消费并行度
  • 批量消费
  • 减少组件IO的交互次数
  • 优先级消费
if (maxOffset - curOffset > 100000) {  // TODO 消息堆积情况的优先处理逻辑  // 未处理的消息可以选择丢弃或者打日志  return ConsumeConcurrentlyStatus.CONSUME_SUCCESS;}// TODO 正常消费过程return ConsumeConcurrentlyStatus.CONSUME_SUCCESS;

10)如何设计消息队列

需要支持快速水平扩容,broker+ partition,partition放在不同的机器上,增加机器时将数据根据topic做迁移,分布式需要考虑一致性,可用性,分区容错性。

  • 一致性:生产者的消息确认、消费者的幂等性、Broker的数据同步;

  • 可用性:数据如何保证不丢不重、数据如何持久化、持久化时如何读写;

  • 分区容错:采用何种选举机制、如果进行多副本同步;
  • 海量数据:如何解决消息积压,海量Topic性能下降;

性能上,可以借鉴时间轮、零拷贝、IO多路复用、顺序读写、压缩批处理

参考文章:

这些年背过的面试题——Kafka篇

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/763149.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

C# 属性

C# 属性 访问器(Accessors) using System; using System.Collections.Generic; using System.Diagnostics; using System.IO; using System.Linq; using System.Text; using System.Threading.Tasks;namespace ConsoleApp2 {class Student{private str…

第十五届蓝桥杯模拟考试III_物联网设计与开发官方代码分析

目录 前言:显示界面部分:页面切换:数值的轮回调整:传递数据: 前言: 这次模拟的效果很不好。85分,4h的限时我花了两天完成,这个时间是远远超出要求的,而且最后还只拿到56分&#xff0…

基于electron29版本桌面应用app开发例子

基于electron29版本桌面应用app开发例子 htmljsnode.js 开发模式 生成package.json文件: yarn init --yes 或 npm init --yes 运行打包 yarn dev yarn build # electron与electron-builder版本不兼容问题处理办法: 在package.json中scripts中添加 “…

解决在 yolov8 训练自己的数据集时,matplotlib 中文乱码问题【woodwhales.cn】

为了更好的阅读体验,建议移步至笔者的博客阅读:解决在 yolov8 训练自己的数据集时,matplotlib 中文乱码问题 在 yolov8 训练自己的数据集时,如果 class 字典使用了中文,则在训练过程中会出现形如下面的警告&#xff1a…

力扣242. 有效的字母异位词

思路:字母相互抵消的思路,本题字符串中只包含小写字母26位,那就新建record数组int[26],下标0-25,代表小写字母a-z, 需要通过 某字符减a 来达到这一目的; class Solution {public boolean isAnagram(String…

ginblog博客系统/golang+vue

ginblog博客系统 前台: 后台: Gitee的项目地址,点击进入下载 注意: 数据库文件导入在model里面,直接导入即可。 admin和front前后台系统记住修改https里的地址为自己的IP地址: front同上。

两数之和(python)

官方题目描述: 给定一个整数数组 nums 和一个整数目标值 target,请你在该数组中找出 和为目标值 target 的那 两个 整数,并返回它们的数组下标。 你可以假设每种输入只会对应一个答案。但是,数组中同一个元素在答案里不能重复出现…

JSONP 实现跨域请求案例

后端使用 express 搭建,案例代码如下: const express require(express)const app express() const PORT 3000app.get(/data, (req, res) > {const jsonData {name: Alan,age: 666,city: GD}const callback req.query.callback // 获取前端中的回…

布隆过滤器原理介绍和典型应用案例

整理自己过去使用布隆过滤器的应用案例和理解 基本介绍 1970年由布隆提出的一种空间效率很高的概率型数据结构,它可以用于检索一个元素是否在一个集合中,由只存0或1的位数组和多个hash算法, 进行判断数据 【一定不存在或者可能存在的算法】 如果这些…

【机器学习300问】43、回归模型预测效果明明很好,为什么均方根误差很大?

一、案例描述 假设我们正在构建一个房地产价格预测模型,目标是预测某个城市各类住宅的售价。模型基于大量房屋的各种特征(如面积、地段、房龄、楼层等)进行训练。 回归模型在大部分情况下对于住宅价格预测非常精准,用户反…

java Flink(四十三)Flink Interval Join源码解析以及简单实例

背景 之前我们在一片文章里简单介绍过Flink的多流合并算子 java Flink(三十六)Flink多流合并算子UNION、CONNECT、CoGroup、Join 今天我们通过Flink 1.14的源码对Flink的Interval Join进行深入的理解。 Interval Join不是两个窗口做关联,…

2.Redis有五种主要的数据类型

Redis有五种主要的数据类型 String(字符串):String类型是最简单的数据类型,可以存储任意类型的数据,例如整数、浮点数、字符串等。String类型支持一些基本的操作,如设置值、获取值、增减值等。 Hash&#…

论文笔记:Llama 2: Open Foundation and Fine-Tuned Chat Models

导语 Llama 2 是之前广受欢迎的开源大型语言模型 LLaMA 的新版本,该模型已公开发布,可用于研究和商业用途。本文记录了阅读该论文的一些关键笔记。 链接:https://arxiv.org/abs/2307.09288 1 引言 大型语言模型(LLMs&#xff…

cesium Clock JulianDate 日照分析

cesium在初始化的时候会自动把Clock对象挂载到容器上Clock内部以JulianDate维护时间,比北京时间慢8个小时,想显示北京时间需要计算时差JulianDate的日期部分和秒数部分是分开的 julianDayNumber:指整数天,记录从公元前4713年正午以…

【蓝桥杯】第15届蓝桥杯青少组stema选拔赛C++中高级真题答案(20240310)

一、选择题 第 1 题 第 2 题 表达式1000/3的结果是( A )。 A.333 B.333.3 C.334 D.333.0 第 3 题 下列选项中,判断a等于1并且b等于1正确的表达式是( B )。 A.!((a!1)&&(b!1)) B.!((a!1)||(b!1)) C.!(a1)&&(b1) D.(a1)&&(b1) 【解析】 A…

我的春招求职面经

智能指针在面试时经常被问到,最近自己也在写,有一点思考,于是找到了这样一个题目,可以看看,上面这个代码有什么问题?留言区说出你的答案吧! 最后分享一下之前的实习->春招->秋招等文章汇总…

huggingface的transformers训练bert

目录 理论 实践 理论 https://arxiv.org/abs/1810.04805 BERT(Bidirectional Encoder Representations from Transformers)是一种自然语言处理(NLP)模型,由Google在2018年提出。它是基于Transformer模型的预训练方法…

YOLOv9有效改进|CVPR2023即插即用的到残差注意力机制(轻量化注意力机制)Inverted Residual Mobile Block

专栏介绍:YOLOv9改进系列 | 包含深度学习最新创新,助力高效涨点!!! 一、改进点介绍 在YOLOv9中加入CVPR2023即插即用的到残差注意力机制。 二、模块详解 2.1 模块简介 Inverted Residual Mobile Block结合了倒置残差块…

JavaEE企业开发新技术3

目录 2.11 Method的基本操作-1 文字性概念描述 代码: 2.12 Method的基本操作-2 2.13 Method的基本操作-3 2.14 数组的反射操作-1 文字性概念: 代码: 2.15 数组的反射操作-2 学习内容 2.11 Method的基本操作-1 文字性概念描述 Me…

SSM整合Springboot

1.0 概述 1.1 持久层: DAO层(mapper) DAO层:DAO层主要是做数据持久层的工作,负责与数据库进行联络的一些任务都封装在此 DAO层的设计首先是设计DAO的接口, 然后在spring-mapper.xml的配置文件中定义此接…