暂无图片
暂无图片
暂无图片
暂无图片
暂无图片

Kafka八股文(查缺补漏)

阿斌Java之路 2022-07-04
1581

为什么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情况就更糟了。




END



后台回复关键词 kafka 获取今日推荐资料

微信8.0新增了一万的好友数,之前没加上好友的可以加一下我的个人微信,再晚又满了,一起抱团取暖结伴内卷。



扫码拉群,学习打卡,交流经验


每周一读




文章转载自阿斌Java之路,如果涉嫌侵权,请发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

评论