现如今,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 >= 3
2. 同步正本列表(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:微信搜搜一搜:大数据技术与数仓