• 【Kafka面试】面试题一


    为什么kafka不做读写分离?

    读写分离是指生产者发送到Leader副本,消费者从Follower副本读取。

    1. 延时问题:数据从leader副本到follow副本是需要过程的,从网络》主节点内存》主节点磁盘》网络》从节点内存》从节点磁盘,比较耗时不适合对实时性要求高的应用。
    2. 负载均衡:读写分离,很大一部分原因是怕同一个节点负载过大。但是kafka通过分区的负载均衡,天然的就均衡了各个broker的压力。

    如何保证kafka消息可靠性?

    • 生产端:ack设置为-1,保证消息同步到follower副本。发送消息方式设置为同步或者异步,做好失败回滚措施
    • broker端:页缓存pagecache设置直接刷盘模式,确保不会有消息在页缓存中的时候宕机。
    • 消费端:关闭消息自动提交,改为手动提交。避免消息没消费完就提交了offset导致消息丢失

    要保证严格的可靠性,就会失去一部分可用性,需要平衡。

    kafka 为什么这么快?

    • 顺序读写:磁盘分为顺序读写与随机读写,基于磁盘的随机读写确实很慢,但磁盘的顺序读写性能却很高,kafka 这里采用的就是顺序读写。
    • Page Cache:为了优化读写性能,Kafka 利用了操作系统本身的 Page Cache。数据直接写入page cache定时刷新脏页到磁盘即可。消费者拉取消息时,如果数据在page cache中,甚至能不需要去读磁盘io。读操作可直接在 Page Cache 内进行。如果 消费和生产速度相当,甚至不需要通过物理磁盘(直接通过 Page Cache)交换数据。

    Broker 收到数据后,写磁盘时只是将数据写入 Page Cache,并不保证数据一定完全写入磁盘。从这一点看,可能会造成机器宕机时,Page Cache 内的数据未写入磁盘从而造成数据丢失。但是这种丢失只发生在机器断电等造成操作系统不工作的场景,而这种场景完全可以由 Kafka 层面的 Replication 机制去解决。如果为了保证这种情况下数据不丢失而强制将 Page Cache 中的数据 Flush 到磁盘,反而会降低性能。也正因如此,Kafka 虽然提供了flush.messages和flush.ms两个参数将 Page Cache 中的数据强制 Flush 到磁盘,但是 Kafka 并不建议使用。

    • 零拷贝:Kafka使用了零拷贝技术,也就是直接将数据从内核空间的读缓冲区直接拷贝到内核空间的 socket 缓冲区,然后再写入到 NIC 缓冲区,避免了在内核空间和用户空间之间穿梭。
    • 分区分段+稀疏索引:Kafka 的 message 是按 topic分 类存储的,topic 中的数据又是按照一个一个的 partition 即分区存储到不同 broker 节点。每个 partition 对应了操作系统上的一个文件夹,partition 实际上又是按照segment分段存储的。通过这种分区分段的设计,Kafka 的 message 消息实际上是分布式存储在一个一个小的 segment 中的,每次文件操作也是直接操作的 segment。为了进一步的查询优化,Kafka 又默认为分段后的数据文件建立了索引文件,就是文件系统上的.index文件。这种分区分段+索引的设计,不仅提升了 数据读取的效率,同时也 提高了数据操作的并行度。
    • 批量读写:生产者可以借助累加器,批量发送消息,消费者也可以批量拉取消费。Kafka 数据读写也是批量的而不是单条的,这样可以避免在网络上频繁传输单个消息带来的延迟和带宽开销。假设网络带宽为10MB/S,一次性传输10MB的消息比传输1KB的消息10000万次显然要快得多。
    • 数据压缩:Producer 可将数据压缩后发送给 broker,从而减少网络传输代价,目前支持的压缩算法有:Snappy、Gzip、LZ4。数据压缩一般都是和批处理配套使用来作为优化手段的。

    消息堆积怎么办?

    我们都知道,消息的消费速度取决于消费者的速度,在消费速度不变的情况下,增加分组内消费者的个数,能倍速的提高消费速度。而消费者的个数又受限于分区个数,消费者个数超过分区数后,再提高消费者个数就没有意义。

    为了能够再提高临时的速度,我们还可以设置临时topic在临时主题中,去加大分区数,将所有原消费者直接将消息再次投递到临时topic中,进行更大规模消费群的消费。这是一个取巧的方案,适合解决临时大量消息的堆积。

    分区数越多,吞吐量就会越高吗?

    在一定条件下,分区数的数量是和吞吐量成正比的,分区数和性能也是成正比的。但是超过了限度后,不升反降。

    从以下四个方面来谈谈:

    1.客户端/服务器端需要使用的内存就越多

    • 服务端在很多组件中都维护了分区级别的缓存,比如controller,FetcherManager等,分区数越大,缓存成本也就越大。
    • 消费端的消费线程数是和分区数挂钩的,分区数越大消费线程数也就越多,线程的开销成本也就越大
    • 生产者发送消息有缓存的概念,会为每个分区缓存消息,当积累到一定程度或者时间时会将消息发送到分区,分区越多,这部分的缓存也就越大

    2.文件句柄的开销

    每个 partition 都会对应磁盘文件系统的一个目录。在 Kafka 的数据日志文件目录中,每个日志数据段都会分配两个文件,一个索引文件和一个数据文件。每个 broker 会为每个日志段文件打开一个 index 文件句柄和一个数据文件句柄。因此,随着 partition 的增多,所需要保持打开状态的文件句柄数也就越多,最终可能超过底层操作系统配置的文件句柄数量限制。

    3.越多的分区可能增加端对端的延迟

    Kafka 会将分区 HW 之前的消息暴露给消费者。分区越多则副本之间的同步数量就越多,在默认情况下,每个 broker 从其他 broker 节点进行数据副本复制时,该 broker 节点只会为此工作分配一个线程,该线程需要完成该 broker 所有 partition 数据的复制。

    4.降低高可用性

    Kafka通过副本(replica)机制来保证高可用。具体做法就是为每个分区保存若干个副本(replica_factor指定副本数)。每个副本保存在不同的broker上。其中的一个副本充当leader 副本,负责处理producer和consumer请求。其他副本充当follower角色,由Kafka controller负责保证与leader的同步。如果leader所在的broker挂掉了,contorller会检测到然后在zookeeper的帮助下重选出新的leader——这中间会有短暂的不可用时间窗口,虽然大部分情况下可能只是几毫秒级别。但如果你有10000个分区,10个broker,也就是说平均每个broker上有1000个分区。此时这个broker挂掉了,那么zookeeper和controller需要立即对这1000个分区进行leader选举。比起很少的分区leader选举而言,这必然要花更长的时间,并且通常不是线性累加的。如果这个broker还同时是controller情况就更糟了。

  • 相关阅读:
    题目:一个整数,它加上100 后是一个完全平方数, 再加上168 又是一个完全平方数,请问该数是多少?
    vue3硅谷甄选01 | 使用vite创建vue3项目及项目的配置 环境准备 ESLint配置 prettier配置 husky配置 项目集成
    VMware Workstation 与 Device/Credential Guard 不兼容问题
    postgresql基于postgis常用空间函数
    HttpClient学习(Java)
    STM32G030F6 (SOP-20)Cortex ® -M0+, 32KB Flash, 8KB RAM, 17 GPIOs
    Go 语言高级网络编程
    2022年湖南大学信息科学与工程学院计算机考博申博经验分享
    智能驾驶ADAS算法设计及Prescan仿真(2): 自适应巡航ACC控制策略设计与simulink仿真
    Vue的模板语法(下)
  • 原文地址:https://blog.csdn.net/qq_21267357/article/details/125608588