Kafka面试问题

 

kafka架构:

Kafka面试问题_第1张图片

kafka介绍:

官方:分布式发布/订阅的消息系统

是一个分布式的、支持分区(partition)、多副本的(replica),基于zookeeper协调的分布式消息系统,最大特征就是:实时处理大量数据,以满足各种场景,比如:

基于Hadoop的批处理系统,低延迟的实时系统,storm/Spark流式处理引擎,web/nginx日志,访问日志,消息服务等。

kafka由java和scala语言编写,kfak通过zookeeper来管理集群配置

特征:

1.高吞吐量,低延迟:每秒可以处理几十万条消息,延迟最低只有几毫秒,每个topic可以分多个分区

2.可扩展性:kafka集群支持热扩展。

3.持久性、可靠性:消息被持久化到磁盘中,并且支持备份保存,以防数据丢失。

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

5.并发:支持数千个端口同时读写

kafka常见面试题

问1:什么是kafka

是一个分布式、支持分区(partition)、多副本的(replica),基于zookeeper协调的分布式消息系统。

问2:kafka最重要的元素是什么

主题:topic,kafka主题是一组或一堆信息

生产者:在kafka中,生产者发布通信,以及向kafka主题topic中发布消息(其实是produce将消息发布到partition中)

消费者:kafka消费者订阅一个主题,并且在主题中获取并处理消息

问3:zookeeper在kafka中的作用是什么

zookeeper的主要作用是在集群中不同节点建立协调,当集群中任何节点失败,我们可以使用zookeeper从先前提交的偏移量中恢复,因为他做周期性提交偏移量工作。

问4:是什么确保了kafka中服务器的负载均衡

领导者(leader)的主要作用是执行分区的所有读写请求任务,而追随者变被动的复制领导者。因此,当领导者挂了时,其中一个追随者接管领导者的角色,可以确保服务器的负载均衡,这些工作是由zookeeper完成的。

问5:为什么kafka的复制至关重要

可以确保发送的消息不丢失,并且可以在发生任何机器错误,程序错误,货软件升级时使用。

问6:启动kafka服务器过程:

先启动zookeeper,再启动kafka

问7:kafka和Flume的主要区别是什么?(单独写一章)

 Flume:管道------个人认为比较适合有多个生产者场景,或者有写入到HDFS、Hbase和kafka需求的场景

 kafka:消息队列-------由于kafka是pull模式,因此适合多个消费者场景。

    目前应用场景:一台日志转发机负责生产日志,后端通过storm消费日志信息,建议可以设置成logs——>kafka——>storm。如果以后有写入到Hbase和HDFS的需求,可以在kafka再接上storm,或者日志转发机上直接日志落地,通过fume去读取日志消息。

问8:列举几个kafka的使用场景

总结下来就几个字:异步处理、日常系统解耦、流量削峰、提速、广播

如果说的再具体一点就是:消息,网站活动追踪。检测指标,日志聚合,流处理,事件采集,提交日志等。

1.异步处理

场景说明:当用户注册之后,需要发送注册邮件和注册短信。传统做法有两种:1.串行方式,2.并行方式

(1)串行方式:将注册信息写入到数据库成功后,发送注册邮件,再发送注册短信。以上三个任务全部完成之后,再返回到客户端。

(2)并行方式:将注册信息写入数据库成功后,发送注册邮件的同时,发送注册短信。以上三个任务完成后,返回给客户端。与串行的差别是,并行的方式可以提高处理的时间。

假设三个业务节点每个使用50毫秒钟,不考虑网络等其他开销,则串行方式的时间是150毫秒,并行的时间可能是100毫秒。

因为CPU在单位时间内处理的请求数是一定的,假设CPU1秒内吞吐量是100次。则串行方式1秒内CPU可处理的请求量是7次(1000/150)。并行方式处理的请求量是10次(1000/100)

小结:如以上案例描述,传统的方式系统的性能(并发量,吞吐量,响应时间)会有瓶颈。如何解决这个问题呢?

引入消息队列,将不是必须的业务逻辑,异步处理。改造后的框架如下:

按照以上约定,用户的响应时间相当于是注册信息写入到数据库的时间,也就是50毫秒。注册邮件,发送短信写入到消息队列后,直接返回,因此写入到消息队列的时间很快,基本可以忽略。,因此用户的响应时间可能是50毫秒。因此架构改变后,系统的吞吐量提高到每秒20 QPS。比串行提高了3倍,比并行提高了两倍

2.应用解耦

场景说明:用户下单后,订单系统需要通知库存系统,传统做法是订单系统调用库存系统的接口。

传统模式缺点:

假如库存系统无法访问,或者订单减库存失败。造成造成订单失败。

所以订单系统和库存系统之间存在耦合。

引入消息队列后的方案:

订单系统:用户下单之后,订单系统完成持久化处理,将消息写入到消息队列,返回给用户下单成功。

库存系统:订阅下单消息,采用拉/推方式,获取下单信息,库存系统根据下单信息,进行库存操作。

假如:在下单时库存系统不能正常使用时,也不影响正常下单,因为在下单后,订单系统写入到消息队列后就不再关心其他后续操作了。实现了订单系统和库存系统之间耦合。

3.流量削峰

流量削峰也是消息队列中常用场景,一般在秒杀和团抢活动中使用广泛。

应用场景:秒杀活动,一般会因为流量过大,导致流量暴增,应用挂掉。为解决这个问题,一般需要在应用前端加入消息队列。

可以控制活动人数、可以缓解短时间高流量压垮应用。

  • 用户的请求,服务器接收后,首先写入到消息队列,假如消息队列长度超过最大数量,则直接抛弃用户请求或跳转到错误页面。

秒杀业务根据消息队列中的请求消息,再做后续处理。

4.日志处理

日志处理是指将消息队列用在日志处理中,比如kafka应用,解决大量日志传输问题,框架简化如下:

日志采集客户端:负责日志数据采集,定时写入到kafka队列

kafka消息队列:负责日志数据的接收,存储和转发

日志处理应用:订阅并消费kafka队列中的日志数据

以下是新浪日志处理应用案例:

(1)Kafka:接收用户日志的消息队列

(2)Logstash:做日志解析,统一成JSON输出给Elasticsearch

(3)Elasticsearch:实时日志分析服务的核心技术,一个schemaless,实时的数据存储服务,通过index组织数据,兼具强大的搜索和统计功能

(4)Kibana:基于Elasticsearch的数据可视化组件,超强的数据可视化能力是众多公司选择ELK stack的重要原因

为什么选择kafka?

高吞吐量,大数据消息系统唯一选择。

问9:Kafka消息是采用Pull模式,还是Push模式?

  kafka一般包括多个生产者(producer),多个Broker(kafka支持水平扩展,一般Broker越多,吞吐量越高),多个消费者(Consumer),以及一个zookeeper集群。kafka通过zookeeper来管理集群配置、选举机制以及消费者发生变化时进行Rebalance。

  生产者使用push模式将消息发布到Broker,消费者使用pull模式从Broker订阅消息。

  push模式很难适应消费速率不同的消费者,如果push速度太快,容易造成消费者拒绝服务或者网络堵塞,如果push速度太慢,容易造成消费者性能浪费。但是消费者采用pull方式也有一个缺点,那就是当Broker没有消息时,消费者会陷入不断轮询中,为了避免这一点,kafka有个参数让消费者产生阻塞指定知道否有新的消息到达。

问10:kafka与传统的消息系统之间的区别

1、kafka持久化日志,这些日志可以被重复读取和无限期保留。

2、kafka是一个分布式系统,以集群方式运行,可以灵活伸缩,在内部通过复制数据提升容错能力和高可用性。

3、kafka支持实时的流式处理。

问11:kafka如何保证消息的顺序性

#乱序场景一:

因为一个topic可以有不同partition,kafka只能保证partition内部有序

partition数量=同一个消费者组中消费者数量,可能需要顺序的数据分布到了不同的partition(由生产者发送),导致处理时乱序

解决方案:

1、可以设置topic有且只有一个partition

2、根据业务需要,需要顺序的指定为同一个partition

3、根据业务需要,比如同一个订单,使用同一个key,就可以保证分配到同一个partition上

#乱序场景二:

对于同一业务进入了同一组消费者后,用了多线程来处理消费者消费到的消息,会导致消息乱序

解决方案:

消费者内部根据线程数量设置等量的内存队列,对于需要顺序的一系列业务数据,根据key或者业务数据,放到同一个内存队列中,然后线程从对应的内存队列中取出并操作。

问12:kafka生产者客户端中使用了几个线程来处理,分别是什么?

有两个,分别是主线程和Sender(消息发送者)线程

主线程负责创建消息,然后通过分区器、序列化器、拦截器之后缓存到累加器RecordAccumulator中。

Sender线程:负责将RecordAccumulator中消息发送到kafka。

问13:kafka中的分区器、拦截器、序列化器是否了解,他们之间的处理顺序是什么?

分区器:根据键值来确定消息应该处于哪个分区中,默认情况下是轮询方式,可以自行实现分区器接口自定义分区逻辑

拦截器:两个方法,doSend()方法会在序列号之前完成, onAcknowledgement()方法在消息确认或失败时调用 可以添加多个拦截器按顺序执行

序列化器:键序列化器和值序列化器,将键和值都转为二进制流 还有反序列化器 将二进制流转为指定类型数据

处理顺序:拦截器 doSend()--->序列化器--->分区器

问14:“消费组中的消费者的数量如果超过topic分区的数量,那么就会有消费者消费不到数据”,这句话是否正确?如果不正确,那么有没有什么hack的手段?

也对也不对

对:因为通过自定义分区分配策略,可以将一个consumer指定消费到所有partition。

不对:但是如果你不去指定consumer的分区,就会有消费者消费不到数据。

因为一个分区partition为了确保消息的顺序性,只能有一个消费者。

未完待续....

你可能感兴趣的:(大数据,大数据)