常见Kafka面试题及答案总汇
1、如何获取topic主题的列表
bin/ka fka-topics.sh —list —zookeeper localhost:2181
2、 生产者和消费者的命令行是什么?
生产者在主题E发布航
bin/kafka-console-producer.sh -broker-list 192.168.43.49:9092 --topicHello-Kafka 注意这里的IP是server.properties申的listeners的配置。接下来每个新行就是输 入一条新消息。
消费者接受消息:
bin/kafka-console-consumer.sh —zookeeper localhost:2181 —topicHello-Kafka ― from-beginning
3、consumer是推还是拉?
customer应该从brokes拉取消息还是brokers将消息推送到consumer,也就是 pull还pusho在这方面,Kafka遵循了一种大部分消息系统的传统设计: producer将消息推送到broker, consumer从broker拉取消息。
push模式,将消息推送到下游的consumero这样做有好处也有坏处:由broker 决定消息推送的速率,对于不同消费速率的consumer就不太好处理了。消息系统 都致力于让consumer以最大的速率最快速的消费消息,但不幸的是,push模式 下,当broker推送的速率远大于consumer消费的速率时,consumer恐怕就要崩 溃了。最终Kafka还是选取了传■统的pull模式。
Pull模式的另外一个好处是consumer可以自主决定是否批量的从broker拉取数 据。Push模式必须在不知道下遊consumer消费能力和消费策略的情况下决定是 立即推送每条消息还是缓存之后批量推送。如果为了避免consumer崩溃而釆用较 低的推送速率,将可能导致一次只推送较少的消息而造成浪费。Pull模式下, consumer就可以根据自己的消费能力去决定这些策略。
Pull有个缺点是,如果broker没有可供消费的消息,将导致consumer不断在循环 中轮询,直到新消息到t达。为了避免这点,Kafka有个参数可以让consumer阻 塞知道新消息到达(当然也可以阻塞知道消息的数量达到某个特定的量这样就可以 批量发送)。
4、 kafka维护消费状态跟踪的方法有什么?
大部分消息系统在broker端的維护消息被消费的记录:一个消息被分发到 consumer后broker就马上进行标记或者等待customer的通知后进行标记。这样 也可以在消息在消费后立马就删除以减少空间占用。
那这样会不会有什么问题呢?
如果一条消息发送岀去之后就立即被标记为消费过的,旦consumer处理消息时失 败了(比如程序崩溃)消息就丢失了。为了解决这个问题,很多消息系统提供了另 外一个个功能:当消息被发送岀去之后仅仅被标记为已发送状态,当接到 consumer已经消费成功的通知后才标记为已被消费的状态。这虽然解决了消息丢 失的问题,但产生了新问题,
首先,如果consumer处理消息成功了但是向broker发送响应时失败了,这条消 息将被消费两次。第二个问题时,broker必须維护每条消息的状态,并且每次都 要先锁住消息然后更改状态然后释放锁。这样麻烦又来了,且不说要維护大量的状 态数据,比如如果消息发送岀去但没有收到消费成功的通知,这条消息将一直处于 被锁定的状态。
Kafka釆用了不同的策略。Topic被分成了若干分区,每个分区在同一时间只被一 个consumer消费。这意味着每个分区被消费的消息在日志中的位置仅仅是一个简 单的整数:offset。这样就很容易标记每个分区消费状态就很容易了,仅仅需要一 个整数而已。这样消费状态的跟踪就很简单了。
这带来了另外一个好处:consumer可以把offset调成一个较老的值,去重新消费 老的消息。
5、 讲一下主从同步
Kafka允许topic的分区拥有若干副本,这个数量是可以配置的,你可以为每个 topic配置副木的数量。Kafka会自动在每个个副本上备份数据,所以当一个节点 down掉时数据依然是可用的。
Kafka的副本功能不是必须的,你可以配置只有一个副本,这样其实就相当于只有 —份数据。
6、 为什么需要消息系统,mysql不能满足需求吗?
(1) 解耦‘
允许你独立的扩展或修改两边的处理过程,只要确保它们遵守同样的接口约束。
(2) 冗余:
消息队列把数据进行持久化直到它们已经被完全处理,通过这一方式规避了数据丢 失风险。许多消息队列所釆用的”插入族取-删除”范式中,在把一个消息从队列中 删除之前,需要你的处理系统明确的指岀该消息已经被处理完毕,从而确保你的数 据被安全的保存直到你使用完毕。
⑶扩展性,
因为消息队列解耦了你的处理过程,所以増大消息入队和处理的频率是很容易的, 只要另外増加处理过程即可。
(4) 灵活性&峰值处理能力:
在访问量剧増的情况下,应用仍然需要继续发挥作用,但是这样的突发流量并不常 见。如果为以能处理这类峰值访问为标准来投入资源随时待命无疑是巨大的浪费。 使用消息队列能够使关键组件顶住突发的访问压力,而不会因为突发的超负荷的请 求而完全崩溃。
(5) 可恢复性,
系统的一部分组件失效时,不会影响到整个系统。消息队列降低了进程间的耦合 度,所以即使一个处理消息的进程挂掉,加入队列中的消息仍然可以在系统恢复后 被处理。
(6) JE5W-UE:
在大多使用场景下,数据处理的顺序都很重要。大部分消息队列本来就是排序的, 并且能保证数据会按照特定的顺序来处理。(Kafka保证一个Partition内的消息的 有序性)
⑺蝕
有助于控制和优化数据流经过系统的速度,解决生产消息和消费消息的处理速度不 —致的情况。
(8)异痢信,
很多时候,用户不想也不需要立即处理消息。消息队列提供了异步处理机制,允许 用户把一个消息放入队列,但并不立即处理它。想向队列中放入多少消息就放多 少,然后在需要的时候再去处理它们。
7、Zookeeper对于Kafka的作用是什么?
Zookeeper是一个开放源码的、高性能的协调服务,它用于Kafka的分布式应用。
Zookeeper主要用于在集群中不同节点之间进行通信
在Kafka中,它被用于提交偏移量,因此如果节点在任何情况下都失败了,它都可 以从之前提交的偏移量中获取除此之外,它还执行其他活动,如Header检测、分 布式同步、配置管理、识别新节点何时离开或连接、集群、节点实时状态等等。
8、 数据传输的事务定义有哪三种?
和MQTT的事务定义一样都是3种。
(1) 最多一次:消息不会被重复发送,最多被传输一次,但也有可能一次不传输
(2) 最少一次:消息不会被漏发送,最少被传输一次,但也有可能被重复传输.
(3) 精确的一次(Exactly once):不会漏传输也不会重复传输,每个消息都传输被 —次而且仅仅被传输一次,这是大家所期望的
9、 Kafka判断一个节点是否还活着有那两个条件?
(1) 节点必须可以維护和ZooKeeper的连接,Zookeeper通过心跳机制检查每个 节点的连接
(2) 如果节点是个follower,他必须能及时的同步leader的写操作,延时不能太久
10、 Kafka与传统MQ消息系统之间有什么区别
(1) .Kafka持久化日志,这些日志可以被重复读取和无限期保留
(2) .Kafka是一个分布式系统:它以集群的方式运行,可以灵活伸缩,在内部通过 复制数据提升容错能力和高可用性
(3) .Kafka支持实时的流式处理
Il、讲一kafka的ack的三种机制
requestrequired.acks 有三个值 0 1 -l(all)
0:生产者不会等待broker的ack,这个延迟最低但是存储的保证最弱当server挂 掉的时候就会丢数据。
1:服务端会等待ack值leader副本确认接收到消息后发送ack但是如果leader挂 掉后他不确保是否复制完成新leader也会导致数据丢失。
-l(all):服务端会等所有的follower的副本受到数据后才会受到leader发岀的 ack,这样数据不会丢失
12、消费者如何不自动提交偏移量,由应用提交?
将enable.auto.commit设为false,然后在处理一批消息后在手动提交或者异步提 交
即:
〃设置使用手动提交offset
$conf->set('enable.auto.commit', 'false'); $topicConf = new RdKafka\TopicConf(); // Set v/here to start consuming messages v/hen there is no initial offse t in // offset store or the desired offset is out of range. // 'smallest1: start from the beginning $topicConf->set('auto.offset.reset', 'smallest'); // Set the configuration to use for subscribed/assigned topics $conf->setDefaultTopicConf($topicConf); ^consumer = new RdKafka\KafkaConsumer($conf); // Subscribe to topic 'test1 $consumer->subscribe(['test1]); while (true) { $message = $consumer->consume(120*1000); switch ($message->err) { case RD_KAFKA_RESP_ERR_NO_ERROR: var_dump($message); //消费完成后手动提交offset //$consumer->commit($message); break; case RD_KAFKA_RESP_ERR_PARTITION_EOF: echo "No more messages; will v/ait for more\n"; break; case RD_KAFKA_RESP_ERR_TIMED_OUT: echo "Timed out\n"; break; default: throw new \Exception($message->errstr(), $message->err(); break; } }
13、消费者故障,岀现活锁问题如何解决?
岀现“活锁”的情况,是它持续的发送心跳,但是没有处理。为了预防消费者在这种 情况下一直持有分区,我们使用max.poll.interval.ms活跃检测机制。在此基础 上,如果你调用的poll的频率大于最大间隔,则客户端将主动地离开组,以便其 他消费者接管该分区。发生这种情况时,你会看到offset提交失败。这是一种安 全机制,保障只有活动成员能够提交offsets所以要留在组中,你必须持续调用 polL
消费者提供两个配置设置来控制poll循环: max.poll.interval.ms:増大poll的间隔,可以为消费者提供更多的时间去处理返回 的消息(调用pollQong)返回的消息,通常返回的消息都是一批)。缺点是此值越 大将会延迟组重新平衡。
max.poll.records:此设置限制每次调用poll返回的消息数,这样可以更容易的预 测 W poll间隔要处理的最大值。通过调整此值,可以减少poll间隔,减少重新 平衡分组的
对于消息处理时间不可预测地的情况,这些选项是不够的。处理这种情况的推荐 方法是将消息处理移到另一个进程中,让消费者继续调用poll。但是必须注意确 保已提交的offset不超过实际位置。另外,你必须禁用自动提交,并只有在进程完 成处理后才为记录手动提交偏移量(取决于你)。还要注意,你需要pause暂停 分区,不会从poll接收到新消息,让进程处理完之前返回的消息(如果你的处理 能力比拉取消息的慢,那创建新进程将导致你机器内存溢岀)。
14. 如何控制消费的位置
kafka使用seek(TopicPartition, long)指定新的消费位置。用于查找服务器保留的最 早和最新的offset的特殊的方法也可用(seekToBeginning(Collection)和 seekToEnd(Collection))
15、 kafka分村(不是单机)的情况下,如何保证消息的时肖费?
Kafka分布式的单位是partition]分区),同一个partition用一个write ahead log组 织,所以可以保证FIFO的顺序。不同partition之间不能保证顺序。但是绝大多数 用户都可以通过message key来定义,因为同一个key的message可以保证只发送 到同一个 partitiono
Kafka中发送1条消息的时候,可以指定(topic, partition, key) 3个参数。partiton 和key是可暨的。如果你拽定了 partition,那就是所有消息发往同1个、 partition,就是有序的。并且在箱费端,Kafka保证,1个partition R能被1个 consumer消费。或者你指定key (比如order id),具有同1个key的所有消 息,会发往同1个partitiono
16、kafka的高可用机制是什么?
多副本冗余的高可用机制
producers broker和 consumer都会拥有多个
分区选举机制、消息确认机制
17、 kafka如何诚少数据丢失
Kafka到底会不会丢数据(data loss)?通常不会,但有些情况下的确有可能会发生。 下面的参数配置及Best practice列表可以较好地保证数据的持久性(当然是tradeoff, 牺牲了吞吐量)。
• block.on.buffer.full = true
• acks = all
• retries = MAX_VALUE
• max.in.flightrequests.per.connection = 1
• 使用 KafkaProducer.sendfrecord, callback)
• callback 逻辑中显式关闭 producer: close(0)
• unclean.leader.election.enable=false
• replication.factor = 3
• min.insync.replicas = 2
• replication.factor > min.insync.replicas
• enable.auto.commit=false
•消息处理完成之后再提交位移
18、 kafka如何不消费重复数据?比如扣款,我们不能重复的扣。
你拿个数据要写库,你先根据主键查一下,如果这数据都有了,你就别插入了, update —下。
比如你是写Redis,那没问题了,反正每次都是set,天然籍等性。
比如你不是上面两个场景,那做的稍微复杂一点,你需要让生产者发送每条数据的 时候,里面加一个全局唯一的id,类似订单id之类的东西,然后你这里消费到了 之后,先根据这个id去比如Redis里查一下,之前消费过吗?如果没有消费过, 你就处理,然后这个id写Redis。如果消费过了,那你就别处理了,保证别重复处 理相同的消息即可。
比如基于数据库的唯一键来保证重复数据不会重复插入多条。因为有唯一键约束 了,重复数据插入只会报错,不会导致数据库中岀现脏数据。
解决:
1慕等操作,重复消费不会产生问题
2.事务
对每个partitionlD,产生一个uniquelD,.只有这个partition的数据被完全消 费,才算成功,否则失败回滚。下次若重复执行,就skip
19、谈谈Kafka吞吐量为何如此高?
多分区、batch sends kafka Reator 网络模型、pagecaches sendfile 零拷贝、数据 、压缩
1〉顺序读写
Kafka是将消息记录持久化到本地磁盘中的,有的人会认为磁盘读写性能差,可能 会对Kafka性能如何保证提岀质疑。实际上不管是内存还是磁盘,快或慢关键在于 寻址的方式,磁盘分为顺序读写与随机读写,内存也一样分为顺序读写与随机读 写。基于磁盘的随机读写确实很慢,但磁盘的顺序读写性能却很高,一般而言要高 岀磁盘随机读写三个数量级,一些情况下磁盘顺序读写性能甚至要高于内存随机读 写。
磁盘的顺序读写是磁盘使用模式中最有规律的,并且操作系统也对这种模式做了大 量优化,Kafka就是使用了磁盘顺序读写来提升的性能。Kafka的message是不断 追加到本地磁盘文件末尾的,而不是随机的写入,这使得Kafka写入吞吐量得到了 显著提升。
Anatomy of a Tbpic
上图就展示了 Kafka是如何写入数据的,每一个Partition其实都是一个文件,收 到消息后Kafka会把数据插入到文件末尾(虚框部分)。
这种方法有一个缺陷一一没有办法删除数据,所以Kafka是不会删除数据的, 它会把所有的数据都保留下来,每个消费者(Consumer)对每个Topic都有一个 offset用来表示读取到了第几条数据。
2〉零拷贝
零拷贝就是一种避免CPU将数据从一块存储拷贝到另外一块存储的技术。
linux操作系统“零拷贝”机制使用了 send句e方法,允许操作系统将数据从 Page Cache直接发送到网络,只需要最后一步的copy操作将数据复制到NIC缓冲 区,这样避免重新复制数据。示意图如下:
通过这种“零拷贝”的机制,Page Cache结合sendfile方法,Kafka消费端的性 能也大幅提升。这也是为什么有时候消费端在不断消费数据时,我们并没有看到磁 盘io比较高,此刻正是操作系统缓存在提供数据。
4〉分区分段+索引
Kafka的message是按topic分类存储的,topic中的数据又是按照一个一个的 partition即分区存储到不同broker节点。每个partition对应了操作系统上的一个 文件夹,partition实际上又是按照segment分段存储的。这也非常符合分布式系 统分区分桶的设计思想。
通过这种分区分段的设计,Kafka的message消息实际上是分布式存储在一 个一个小的segment中的,每次文件操作也是直接操作的segment。为了进一步 的查询优化,Kafka又默认为分段后的数据文件建立了索引文件,就是文件系统上 的.index文件。这种分区分段+索引的设计,不仅提升了数据读取的效率,同时也 提高了数据操作的并行度。
5〉批量读写
Kafka数据读写也是批量的而不是单条的。
在向Kafka写入数据时,可以启用批次写入,这样可以避免在网络上频繁传输 单个消息带来的延迟和带宽开销。假设网络带宽为1OMB/S,—次性传输1OMB的 消息比传输1KB的消息1OOOO万次显然要快得多。
6〉批量压缩
如果每个消息都压缩,但是压缩率相对很低,所以Kafka使用了批量压缩,即 将多个消息一起压缩而不是单个消息压缩
Kafka允许使用递归的消息集合,批量的消息可以通过压缩的形式传输并且在 日志中也可以保持压缩格式,直到被消费者解压缩
Kafka支持多种压缩协议,包括Gzip和Snappy压缩协议
Kafka把所有的消息都变成一个批量的文件,并且进行合理的批量压缩,减少 网络I。损耗,通过mmap提高I/O速度,写入数据的时候由于单个Partion是末 尾添加所以速度最优;读取数据的时候配合sendfile直接暴力输岀。
评论列表