现如今,Kafka已不再是一个单纯的音讯队列零碎。Kafka是一个分布式的流解决平台,被越来越多的公司应用,Kafka能够被用于高性能的数据管道,流解决剖析,数据集成等场景。本文分享总结了几个Kafka常见的面试问题,心愿对你有所帮忙。次要包含以下内容:
- Kafka是如何保障数据不失落的?
- 如何解决Kafka数据失落问题?
- Kafka能够保障永恒不失落数据吗?
- 如何保障Kafka中的音讯是有序的?
- 如何确定Kafka主题的分区数量?
- 如何调整生产环境中Kafka主题的分区数量?
- 如何重均衡Kafka集群?
- 如何查看消费者组是否存在滞后生产?
Q1:Kafka是如何保障数据不失落的?
该问题曾经成为了Kafka面试的常规,如同Java的HashMap,属于高频呈现的面试问题。那么,咱们该怎么了解这个问题呢?问题是Kafka如何保障数据不失落,即Kafka的Broker提供了什么机制保证数据不失落的。
其实对于Kafka的Broker而言,Kafka 的复制机制和分区的多正本架构是Kafka 可靠性保障的外围。把音讯写入多个正本能够使Kafka 在产生解体时仍能保障音讯的持久性。
搞清楚了问题的外围,再来看一下该怎么答复这个问题:次要包含三个方面
1.Topic 正本因子个数:replication.factor >= 32.同步正本列表(ISR):min.insync.replicas = 2
3.禁用unclean选举: unclean.leader.election.enable=false
上面将会逐渐剖析下面的三个配置:
- 正本因子
Kafka的topic是能够分区的,并且能够为分区配置多个正本,该配置能够通过replication.factor
参数实现。Kafka中的分区正本包含两种类型:领导者正本(Leader Replica)和追随者正本(Follower Replica),每个分区在创立时都要选举一个正本作为领导者正本,其余的正本主动变为追随者正本。在 Kafka 中,追随者正本是不对外提供服务的,也就是说,任何一个追随者正本都不能响应消费者和生产者的读写申请。所有的申请都必须由领导者副原本解决。换句话说,所有的读写申请都必须发往领导者正本所在的 Broker,由该 Broker 负责解决。追随者正本不解决客户端申请,它惟一的工作就是从领导者正本异步拉取音讯,并写入到本人的提交日志中,从而实现与领导者正本的同步。
一般来说,正本设为3能够满足大部分的应用场景,也有可能是5个正本(比方银行)。如果正本因子为N,那么在N-1个broker 生效的状况下,依然可能从主题读取数据或向主题写入数据。所以,更高的正本因子会带来更高的可用性、可靠性和更少的故障。另一方面,正本因子N须要至多N个broker ,而且会有N个数据正本,也就是说它们会占用N倍的磁盘空间。理论生产环境中个别会在可用性和存储硬件之间作出衡量。
除此之外,正本的散布同样也会影响可用性。默认状况下,Kafka会确保分区的每个正本散布在不同的Broker上,然而如果这些Broker在同一个机架上,一旦机架的交换机产生故障,分区就会不可用。所以倡议把Broker散布在不同的机架上,能够应用broker.rack参数配置Broker所在机架的名称。
- 同步正本列表
In-sync replica(ISR)称之为同步正本,ISR中的正本都是与Leader进行同步的正本,所以不在该列表的follower会被认为与Leader是不同步的。那么,ISR中存在是什么正本呢?首先能够明确的是:Leader正本总是存在于ISR中。而follower正本是否在ISR中,取决于该follower正本是否与Leader正本放弃了“同步”。
Kafka的broker端有一个参数replica.lag.time.max.ms
, 该参数示意follower正本滞后与Leader正本的最长工夫距离,默认是10秒。这就意味着,只有follower正本落后于leader正本的工夫距离不超过10秒,就能够认为该follower正本与leader正本是同步的,所以哪怕以后follower正本落后于Leader正本几条音讯,只有在10秒之内赶上Leader正本,就不会被踢出出局。
能够看出ISR是一个动静的,所以即使是为分区配置了3个正本,还是会呈现同步正本列表中只有一个正本的状况(其余正本因为不可能与leader及时放弃同步,被移出ISR列表)。如果这个同步正本变为不可用,咱们必须在可用性和一致性之间作出抉择(CAP实践)。
依据Kafka 对可靠性保障的定义,音讯只有在被写入到所有同步正本之后才被认为是已提交的。但如果这里的“所有正本”只蕴含一个同步正本,那么在这个正本变为不可用时,数据就会失落。如果要确保已提交的数据被写入不止一个正本,就须要把最小同步正本数量设置为大一点的值。对于一个蕴含3 个正本的主题分区,如果min.insync.replicas=2 ,那么至多要存在两个同步正本能力向分区写入数据。
如果进行了下面的配置,此时必须要保障ISR中至多存在两个正本,如果ISR中的正本个数小于2,那么Broker就会进行承受生产者的申请。尝试发送数据的生产者会收到NotEnoughReplicasException异样,消费者依然能够持续读取已有的数据。
- 禁用unclean选举
抉择一个同步正本列表中的分区作为leader 分区的过程称为clean leader election。留神,这里要与在非同步正本当选一个分区作为leader分区的过程辨别开,在非同步正本当选一个分区作为leader的过程称之为unclean leader election。因为ISR是动静调整的,所以会存在ISR列表为空的状况,通常来说,非同步正本落后 Leader 太多,因而,如果抉择这些正本作为新 Leader,就可能呈现数据的失落。毕竟,这些正本中保留的音讯远远落后于老 Leader 中的音讯。在 Kafka 中,选举这种正本的过程能够通过Broker 端参数 unclean.leader.election.enable 管制是否容许 Unclean 领导者选举。开启 Unclean 领导者选举可能会造成数据失落,但益处是,它使得分区 Leader 正本始终存在,不至于进行对外提供服务,因而晋升了高可用性。反之,禁止 Unclean Leader 选举的益处在于保护了数据的一致性,防止了音讯失落,但就义了高可用性。分布式系统的CAP实践说的就是这种状况。
可怜的是,unclean leader election的选举过程仍可能会造成数据的不统一,因为同步正本并不是齐全同步的。因为复制是异步实现的,因而无奈保障follower能够获取最新消息。比方Leader分区的最初一条音讯的offset是100,此时正本的offset可能不是100,这受到两个参数的影响:
- replica.lag.time.max.ms:同步正本滞后与leader正本的工夫
- zookeeper.session.timeout.ms:与zookeeper会话超时工夫
简而言之,如果咱们容许不同步的正本成为leader,那么就要承当失落数据和呈现数据不统一的危险。如果不容许它们成为leader,那么就要承受较低的可用性,因为咱们必须期待原先的领袖复原到可用状态。
对于unclean选举,不同的场景有不同的配置形式。对数据品质和数据一致性要求较高的零碎会禁用这种unclean的leader选举(比方银行)。如果在可用性要求较高的零碎里,比方实时点击流剖析零碎, 个别不会禁用unclean的leader选举。
Q2:如何解决Kafka数据失落问题?
你可能会问:这个问题跟Q1有什么区别呢?其实个别在面试问题中能够了解成一个问题。之所以在这里做出辨别,是因为两者的解决形式不一样。Q1问题是从Kafka的Broker侧来对待数据失落的问题,而Q2是从Kafka的生产者与消费者的角度来对待数据失落的问题。
先来看一下如何答复这个问题:次要包含两个方面:
- Producer
- retries=Long.MAX_VALUE
设置 retries 为一个较大的值。这里的 retries 同样是 Producer 的参数,对应后面提到的 Producer 主动重试。当呈现网络的刹时抖动时,音讯发送可能会失败,此时配置了 retries > 0 的 Producer 可能主动重试音讯发送,防止音讯失落。
- acks=all
设置 acks = all。acks 是 Producer 的一个参数,代表了你对“已提交”音讯的定义。如果设置成 all,则表明所有正本 Broker 都要接管到音讯,该音讯才算是“已提交”。这是最高等级的“已提交”定义。
- max.in.flight.requests.per.connections=1
该参数指定了生产者在收到服务器晌应之前能够发送多少个音讯。它的值越高,就会占用越多的内存,不过也会晋升吞吐量。把它设为1 能够保障音讯是依照发送的程序写入服务器的,即便产生了重试。
- Producer要应用带有回调告诉的API,也就是说不要应用 producer.send(msg),而要应用 producer.send(msg, callback)。
- 其余错误处理
应用生产者内置的重试机制,能够在不造成音讯失落的状况下轻松地解决大部分谬误,不过
依然须要解决其余类型的谬误,例如音讯大小谬误、序列化谬误等等。- Consumer
- 禁用主动提交:enable.auto.commit=false
- 消费者解决完音讯之后再提交offset
- 配置auto.offset.reset
这个参数指定了在没有偏移量可提交时(比方消费者第l次启动时)或者申请的偏移量在broker上不存在时(比方数据被删了),消费者会做些什么。
这个参数有两种配置。一种是earliest:消费者会从分区的开始地位读取数据,不论偏移量是否无效,这样会导致消费者读取大量的反复数据,但能够保障起码的数据失落。一种是latest(默认),如果抉择了这种配置, 消费者会从分区的开端开始读取数据,这样能够缩小反复解决音讯,但很有可能会错过一些音讯。
Q3:Kafka能够保障永恒不失落数据吗?
下面剖析了一些保障数据不失落的措施,在肯定水平上能够防止数据的失落。然而请留神:Kafka 只对“已提交”的音讯(committed message)做有限度的长久化保障。所以说,Kafka不可能齐全保证数据不失落,须要做出一些衡量。
首先,要了解什么是已提交的音讯,当 Kafka 的若干个 Broker 胜利地接管到一条音讯并写入到日志文件后,它们会通知生产者程序这条音讯已胜利提交。此时,这条音讯在 Kafka 看来就正式变为已提交音讯了。所以说无论是ack=all,还是ack=1,不管哪种状况,Kafka 只对已提交的音讯做长久化保障这件事件是不变的。
其次,要了解有限度的长久化保障,也就是说 Kafka 不可能保障在任何状况下都做到不失落音讯。必须保障Kafka的Broker是可用的,换句话说,如果音讯保留在 N 个 Kafka Broker 上,那么这个前提条件就是这 N 个 Broker 中至多有 1 个存活。只有这个条件成立,Kafka 就能保障你的这条音讯永远不会失落。
总结一下,Kafka 是能做到不失落音讯的,只不过这些音讯必须是已提交的音讯,而且还要满足肯定的条件。
Q4:如何保障Kafka中的音讯是有序的?
首先须要明确的是:Kafka的主题是分区有序的,如果一个主题有多个分区,那么Kafka会依照key将其发送到对应的分区中,所以,对于给定的key,与其对应的record在分区内是有序的。
Kafka能够保障同一个分区里的音讯是有序的,即生产者依照肯定的程序发送音讯,Broker就会依照这个程序将他们写入对应的分区中,同理,消费者也会依照这个程序来生产他们。
在一些场景下,音讯的程序是十分重要的。比方,先存钱再取钱与先取钱再存钱是截然不同的两种后果。
下面的问题中提到一个参数max.in.flight.requests.per.connections=1,该参数的作用是在重试次数大于等于1时,保证数据写入的程序。如果该参数不为1,那么当第一个批次写入失败时,第二个批次写入胜利,Broker会重试写入第一个批次,如果此时第一个批次重试写入胜利,那么这两个批次音讯的程序就反过来了。
一般来说,如果对音讯的程序有要求,那么在为了保障数据不失落,须要先设置发送重试次数retries>0,同时须要把max.in.flight.requests.per.connections参数设为1,这样在生产者尝试发送第一批音讯时,就不会有其余的音讯发送给broker,尽管会影响吞吐量,然而能够保障音讯的程序。
除此之外,还能够应用单分区的Topic,然而会重大影响吞吐量。
Q5:如何确定适合的Kafka主题的分区数量?
抉择适合的分区数量能够达到高度并行读写和负载平衡的目标,在分区上达到平衡负载是实现吞吐量的要害。须要依据每个分区的生产者和消费者的冀望吞吐量进行预计。
举个栗子:假如冀望读取数据的速率(吞吐量)为1GB/Sec,而一个消费者的读取速率为50MB/Sec,此时至多须要20个分区以及20个消费者(一个消费者组)。同理,如果冀望生产数据的速率为1GB/Sec,而每个生产者的生产速率为100MB/Sec,此时就须要有10个分区。在这种状况下,如果设置20个分区,既能够保障1GB/Sec的生产速率,也能够保障消费者的吞吐量。通常须要将分区的数量调整为消费者或者生产者的数量,只有这样才能够同时实现生产者和消费者的吞吐量。
一个简略的计算公式为:分区数 = max(生产者数量,消费者数量)
- 生产者数量=整体生产吞吐量/每个生产者对单个分区的最大生产吞吐量
- 消费者数量=整体生产吞吐量/每个消费者从单个分区生产的最大吞吐量
Q6:如何调整生产环境中Kafka主题的分区数量?
须要留神的是:当咱们减少主题的分区数量时,会违反同一个key进行同一个分区的事实。咱们能够创立一个新的主题,使得该主题有更多的分区数,而后暂停生产者,将旧的主题中的数据复制到新的主题中,而后将消费者和生产者切换到新的主题,操作起来会十分辣手。
Q7:如何重均衡Kafka集群?
在上面状况产生时,须要重均衡集群:
- 主题分区在整个集群里的不平衡散布造成了集群负载的不平衡。
- broker离线造成分区不同步。
- 新退出的broker 须要从集群里取得负载。
应用kafka-reassign-partitions.sh命令进行重均衡
Q8:如何查看消费者组是否存在滞后生产?
咱们能够应用kafka-consumer-groups.sh命令进行查看,比方:
$ bin/kafka-consumer-groups.sh --bootstrap-server cdh02:9092 --describe --group my-group## 会显示上面的一些指标信息TOPIC PARTITION CURRENT-OFFSET LOG-END-OFFSET LAG CONSUMER-ID HOST CLIENT-ID主题 分区 以后offset LEO 滞后音讯数 消费者id 主机 客户端id
个别状况下,如果运行良好,CURRENT-OFFSET的值会与LOG-END-OFFSET 的值十分靠近。通过这个命令能够查看哪个分区的生产呈现了滞后。
总结
本文次要分享了8个常见的Kafka面试题,对于每个题目都给出了相应的答案。对照这些问题,置信会对Kafka会有更粗浅的意识。
gzh:微信搜搜一搜:大数据技术与数仓