kafka常见问题

kafka Controller主要负责哪些事情

Kafka Controller是Kafka集群中的一个特殊角色,负责管理和协调整个Kafka集群的状态和元数据。它主要负责以下几个方面的工作:

  1. Broker管理:Controller负责监控和管理Kafka集群中的所有Broker节点。它会检测Broker分区副本以实现负载均衡和故障恢复。

  2. 分区分配:Controller负责分配新创建的主题的分区以及分区的副本。它会根据集群的负载情况和副本的可用性,选择合适的Broker来分配分区副本。

  3. Leader选举:Controller负责监控分区的Leader状态,并在Leader失效时进行重新选举。它会选择一个新的Broker作为分区的Leader,并通知其他Broker更新元数据。

  4. Topic管理:Controller负责处理主题的创建、删除和配置变更等操作。它会监控主题的状态,并确保主题的元数据在整个集群中保持一致。

  5. 集群状态管理:Controller负责监控整个Kafka集群的状态,并处理集群中的异常情况。它会检测Broker的故障和恢复,并触发相应的操作来保持集群的稳定性和可用性。

总之,Kafka Controller是Kafka集群的"大脑",负责管理和协调整个集群的运行状态,确保数据的可靠传输和高可用性。

Kafka磁盘顺序写保证写数据性能

kafka写数据:顺序写,往磁盘上写数据时,就是追加数据,没有随机写的操作。经验: 如果一个服务器磁盘达到一定的个数,磁盘也达到一定转数,往磁盘里面顺序写(追加写)数据的速度和写内存的速度差不多生产者生产消息,经过kafka服务先写到os cache 内存中,然后经过sync顺序写到磁盘上

Kafka零拷贝机制保证读数据高性能

消费者读取数据流程:

消费者发送请求给kafka服务
kafka服务去os cache缓存读取数据(缓存没有就去磁盘读取数据)
从磁盘读取了数据到os cache缓存中
os cache复制数据到kafka应用程序中
kafka将数据(复制)发送到socket cache中
socket cache通过网卡传输给消费者
在这里插入图片描述

kafka linux sendfile技术 — 零拷贝

1.消费者发送请求给kafka服务
2.kafka服务去os cache缓存读取数据(缓存没有就去磁盘读取数据)
3.从磁盘读取了数据到os cache缓存中
4.os cache直接将数据发送给网卡
5.通过网卡将数据传输给消费者

在这里插入图片描述

Kafka日志分段保存

Kafka中一个主题,一般会设置分区;比如创建了一个topic_a,然后创建的时候指定了这个主题有三个分区。其实在三台服务器上,会创建三个目录。服务器1(kafka1)创建目录topic_a-0:。目录下面是我们文件(存储数据),kafka数据就是message,数据存储在log文件里。.log结尾的就是日志文件,在kafka中把数据文件就叫做日志文件 。一个分区下面默认有n多个日志文件(分段存储),一个日志文件默认1G。

在这里插入图片描述

Kafka二分查找定位数据

Kafka里面每一条消息,都有自己的offset(相对偏移量),存在物理磁盘上面,在position
Position:物理位置(磁盘上面哪个地方)也就是说一条消息就有两个位置:offset:相对偏移量(相对位置)position:磁盘物理位置

稀疏索引: Kafka中采用了稀疏索引的方式读取索引,kafka每当写入了4k大小的日志(.log),就往index里写入一个记录索引。其中会采用二分查找

在这里插入图片描述
ISR,通信请求或同步数据,则该 Follower 将被踢出 ISR。该时间阈值由 replica.lag.time.max.ms参数设定,默认 30s。表示和 Leader 保持同步的 Follower 集合。

如果 replica.lag.time.max.ms 是 Apache Kafka 中的一个配置参数,用于设置副本(replica)之间的最大延迟时间。副本是 Kafka 中用于实现高可用性和数据冗余的概念,每个分区(partition)可以有多个副本。当一个副本与其主副本(leader replica)之间的延迟超过 replica.lag.time.max.ms 设置的值时,Kafka 将认为该副本已经滞后,并可能触发一些操作,如重新分配副本或进行警报。
这个参数的默认值是 10000 毫秒(10秒),可以根据实际需求进行调整。较小的值可以更快地检测到副本滞后的情况,但可能会导致频繁的副本重新分配或警报。较大的值可以减少不必要的操作,但可能会延迟检测到副本滞后的时间。
请注意,replica.lag.time.max.ms 只是一个阈值,实际的副本滞后情况还受到其他因素的影响,如网络延迟、硬件性能等。因此,在设置该参数时需要综合考虑系统的实际情况。Follower 长时间未向 Leader 发送Leader 发生故障之后,就会从 ISR 中选举新的 Leader。

场景四:如果某个broker leader partition过多

正常情况下,我们的leader partition在服务器之间是负载均衡。hadoop1 4 hadoop2 1 hadoop3 1

现在各个业务方可以自行申请创建topic,分区数量都是自动分配和后续动态调整的, kafka本身会自动把leader partition均匀分散在各个机器上,这样可以保证每台机器的读写吞吐量都是均匀的 但是也有例外,那就是如果某些broker宕机,会导致leader partition过于集中在其他少部分几台broker上, 这会导致少数几台broker的读写请求压力过高,其他宕机的broker重启之后都是folloer partition,读写请求很低, 造成集群负载不均衡有一个参数,auto.leader.rebalance.enable,默认是true, 每隔300秒(leader.imbalance.check.interval.seconds)检查leader负载是否平衡 如果一台broker上的不均衡的leader超过了10%,leader.imbalance.per.broker.percentage, 就会对这个broker进行选举 配置参数:auto.leader.rebalance.enable 默认是true leader.imbalance.per.broker.percentage: 每个broker允许的不平衡的leader的比率。如果每个broker超过了这个值,控制器会触发leader的平衡。这个值表示百分比。10% leader.imbalance.check.interval.seconds:默认值300秒

13.1 生产者发送消息原理

在这里插入图片描述

13.3 如何提升吞吐量

如何提升吞吐量:
参数一:buffer.memory:设置发送消息的缓冲区,默认值是33554432,就是32MB
参数二:compression.type:默认是none,不压缩,但是也可以使用lz4压缩,效率还是不错的,压缩之后可以减小数据量,提升吞吐量,但是会加大producer端的cpu开销
参数三:batch.size:设置batch的大小,如果batch太小,会导致频繁网络请求,吞吐量下降;如果batch太大,会导致一条消息需要等待很久才能被发送出去,而且会让内存缓冲区有很大压力,过多数据缓冲在内存里,默认值是:16384,就是16kb,也就是一个batch满了16kb就发送出去,一般在实际生产环境,这个batch的值可以增大一些来提升吞吐量,如果一个批次设置大了,会有延迟。一般根据一条消息大小来设置。如果我们消息比较少。配合使用的参数linger.ms,这个值默认是0,意思就是消息必须立即被发送,但是这是不对的,一般设置一个100毫秒之类的,这样的话就是说,这个消息被发送出去后进入一个batch,如果100毫秒内,这个batch满了16kb,自然就会发送出去。

13.4 如何处理异常

LeaderNotAvailableException:这个就是如果某台机器挂了,此时leader副本不可用,会导致你写入失败,要等待其他follower副本切换为leader副本之后,才能继续写入,此时可以重试发送即可;如果说你平时重启kafka的broker进程,肯定会导致leader切换,一定会导致你写入报错,是LeaderNotAvailableException。
NotControllerException:这个也是同理,如果说Controller所在Broker挂了,那么此时会有问题,需要等待Controller重新选举,此时也是一样就是重试即可。
NetworkException:网络异常 timeout a. 配置retries参数,他会自动重试的 b. 但是如果重试几次之后还是不行,就会提供Exception给我们来处理了,我们获取到异常以后,再对这个消息进行单独处理。我们会有备用的链路。发送不成功的消息发送到Redis或者写到文件系统中,甚至是丢弃。

重试机制

重试会带来一些问题:

消息会重复有的时候一些leader切换之类的问题,需要进行重试,设置retries即可,但是消息重试会导致,重复发送的问题,比如说网络抖动一下导致他以为没成功,就重试了,其实人家都成功了.
消息乱序消息重试是可能导致消息的乱序的,因为可能排在你后面的消息都发送出去了。所以可以使用"max.in.flight.requests.per.connection"参数设置为1, 这样可以保证producer同一时间只能发送一条消息。两次重试的间隔默认是100毫秒,用"retry.backoff.ms"来进行设置 基本上在开发过程中,靠重试机制基本就可以搞定95%的异常问题。

ACK参数详解

producer端设置的 request.required.acks=0;只要请求已发送出去,就算是发送完了,不关心有没有写成功。性能很好,如果是对一些日志进行分析,可以承受丢数据的情况,用这个参数,性能会很好。
request.required.acks=1;发送一条消息,当leader partition写入成功以后,才算写入成功。不过这种方式也有丢数据的可能。request.required.acks=-1;需要ISR列表里面,所有副本都写完以后,这条消息才算写入成功。
ISR:1个副本。1 leader partition 1 follower partition kafka服务端:min.insync.replicas:1, 如果我们不设置的话,默认这个值是1 一个leader partition会维护一个ISR列表,这个值就是限制ISR列表里面 至少得有几个副本,比如这个值是2,那么当ISR列表里面只有一个副本的时候。往这个分区插入数据的时候会报错。
设计一个不丢数据的方案:数据不丢失的方案
1)分区副本 >=2
2)acks = -1
3)min.insync.replicas >=2 还有可能就是发送有异常:对异常进行处理
综合案例演示
消费组概念 groupid相同就属于同一个消费组
1)每个consumer都要属于一个consumer.group,就是一个消费组,topic的一个分区只会分配给 一个消费组下的一个consumer来处理,每个consumer可能会分配多个分区,也有可能某个consumer没有分配到任何分区
2)如果想要实现一个广播的效果,那只需要使用不同的group id去消费就可以。topicA: partition0、partition1 groupA:consumer1:消费 partition0 consuemr2:消费 partition1 consuemr3:消费不到数据 groupB: consuemr3:消费到partition0和partition1 3)如果consumer group中某个消费者挂了,此时会自动把分配给他的分区交给其他的消费者,如果他又重启了,那么又会把一些分区重新交还给他
*

14.3 偏移量管理

每个consumer内存里数据结构保存对每个topic的每个分区的消费offset,定期会提交offset,老版本是写入zk,但是那样高并发请求zk是不合理的架构设计,zk是做分布式系统的协调的,轻量级的元数据存储,不能负责高并发读写,作为数据存储。
现在新的版本提交offset发送给kafka内部topic:__consumer_offsets,提交过去的时候, key是group.id+topic+分区号,value就是当前offset的值,每隔一段时间,kafka内部会对这个topic进行compact(合并),也就是每个group.id+topic+分区号就保留最新数据。
__consumer_offsets可能会接收高并发的请求,所以默认分区50个(leader partitiron -> 50 kafka),这样如果你的kafka部署了一个大的集群,比如有50台机器,就可以用50台机器来抗offset提交的请求压力. 消费者 -> broker端的数据 message -> 磁盘 -> offset 顺序递增 从哪儿开始消费?-> offset 消费者(offset)

消费异常感知

heartbeat.interval.ms:consumer心跳时间间隔,必须得与coordinator保持心跳才能知道consumer是否故障了, 然后如果故障之后,就会通过心跳下发rebalance的指令给其他的consumer通知他们进行rebalance的操作
session.timeout.ms:kafka多长时间感知不到一个consumer就认为他故障了,默认是10秒
max.poll.interval.ms:如果在两次poll操作之间,超过了这个时间,那么就会认为这个consume处理能力太弱了,会被踢出消费组,分区分配给别人去消费,一般来说结合业务处理的性能来设置就可以了。

max.poll.interval.ms 是一个 Kafka 消费者配置参数,用于控制消费者在没有调用 poll()
方法时的最大空闲时间。当消费者在指定的时间内没有调用 poll() 方法来获取新的消息时,Kafka
将认为消费者已经失去了与集群的连接,并将其视为已经死亡。

默认情况下,max.poll.interval.ms 的值是 300000 毫秒(即 5 分钟)。这意味着如果消费者在 5
分钟内没有调用 poll() 方法,Kafka 将认为消费者已经失去连接,并将其从消费者组中移除。

通过增加 max.poll.interval.ms
的值,可以允许消费者在更长的时间内保持空闲,而不被认为失去连接。这对于处理大量数据或者需要较长时间处理每条消息的消费者来说是有用的。然而,增加这个值也会增加消费者失去连接后重新平衡的时间。

需要根据具体的应用场景和消费者的处理能力来调整 max.poll.interval.ms 的值,以平衡消费者的活跃性和

14.6 核心参数解释

fetch.max.bytes:获取一条消息最大的字节数,一般建议设置大一些,默认是1M 其实我们在之前多个地方都见到过这个类似的参数,意思就是说一条信息最大能多大?

Producer 发送的数据,一条消息最大多大, -> 10M Broker 存储数据,一条消息最大能接受多大 -> 10M
Consumer max.poll.records: 一次poll返回消息的最大条数,默认是500条
connection.max.idle.ms:consumer跟broker的socket连接如果空闲超过了一定的时间,此时就会自动回收连接,但是下次消费就要重新建立socket连接,这个建议设置为-1,不要去回收
enable.auto.commit: 开启自动提交偏移量 auto.commit.interval.ms:
每隔多久提交一次偏移量,默认值5000毫秒 _consumer_offset auto.offset.reset:earliest
当各分区下有已提交的offset时,从提交的offset开始消费;无提交的offset时,从头开始消费 topica ->
partition0:1000 partitino1:2000 latest
当各分区下有已提交的offset时,从提交的offset开始消费;无提交的offset时,消费新产生的该分区下的数据 none
topic各分区都存在已提交的offset时,从offset后开始消费;只要有一个分区不存在已提交的offset,则抛出异常

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值