Kafka常见面试题

1. Kafka消息可靠性传输/如何保证消息不丢失

在发送消息到消费者接收消息,每个阶段都可能会丢失消息,所以解决方案也是从多个方面考虑。

第一个是生产者发送消息的时候,可以使用异步回调发送,如果消息发送失败,可以通过回调获取失败后的消息信息,可以考虑重试或者记录日志,后面在做补偿就可以。同时在生产者这边还可以设置消息重试,有的时候是由于网络抖动的原因导致发送不成功,就可以使用重试机制来解决

第二个在broker中消息有可能会丢失。可以通过Kafka的复制机制来确保消息不丢失。在生产者发送消息的时候,可以设置一个acks,就是确认机制。我们可以设置参数为all,这样的话,当生产者发送消息到了分区之后,不仅仅只在leader区保存确认,在follwer区也会保存确认,只有当所有的副本都保存确认以后才算是成功发送了消息,所以,这样设置就很大程度上保证了消息不会在broker丢失。

第三个有可能是在消费者端丢失消息。Kafka消费消息都是按照offset进行标记消费的,消费者默认是自动按期提交已经消费的偏移量,默认是每隔5s提交一次,如果出现重平衡的情况,可能会重复消费或者丢失数据。一般会禁用掉自动提交偏移量,改为手动提交,当消费成功后再报告给broker消费的位置,这样就可以避免消息丢失和重复消费了。

2. Kafka如何防止消息重复消费/消息消费的幂等性

首先kafka的broker上存储的消息,都有一个offset标记,Kafka的消费者是通过offset标记来维护当前已经消费的数据,每消费一批数据,Kafka broker就会更新offset的值,避免重复消费。Kafka消费端的自动提交逻辑有一个默认的5秒间隔,也就是说在5秒之后的下一次向broker拉取消息的时候提交。所以在consumer消费的过程中,应用程序被强制kill或者宕机,可能会导致offset没有提交,从而产生重复消费的问题。

此外,还有一种情况也会出现重复消费。在Kafka中有一个Partition Balance机制,就是把多个Partition均衡的分配给多个消费者。Consumer端会从分配的Partition里面去消费消息,如果consumer在默认的五分钟没办法处理完这一批消息,就会触发Kafka的rebalance机制,从而导致Offset自动提交失败,而在重新rebalance后,consumer还是会从之前没提交的offset位置开始消费,也会导致消息重复消费的问题。

基于这样的背景,解决重复消费问题的方法有这么几个:

1) 提高消费端的处理性能,避免触发balance,比如可以用异步的方式来处理消息,缩短单个消息消费的时长。或者还可以调整消息处理的超时时间,还可以减少一次性从broker上拉取数据的条数

2) 引入消息去重机制,可以针对消息生成md5然后保存到mysql或者redis中,在处理消息之前先去mysql或者redis里面判断是否已经消费过

3) 关闭自动提交偏移量,开启手动提交,采用同步+异步的提交方式

注:保证幂等性主要围绕着消息标识符来讲

在生产端,发送点赞、评论、关注消息的时候,为每条消息分配一个唯一的标识符,可以使用全局唯一的ID或者消息内容的哈希值作为标识符。消费者在处理消息时,可以记录已经处理过的消息标识符,并在接收到重复消息时进行判断和过滤。

3. Kafka如何保证消息的顺序性

Kafka默认存储和消费消息,是不能保证顺序性的,因为一个topic可能存储在不同的分区中,每个分区都有一个按照顺序存储的偏移量,如果消费者关联了多个分区就不能保证顺序性。但同时Kafka还有一个特性:在Kafka中,只保证Partition(分区)内有序,不保证Topic所有分区都是有序的。

基于此,对于kafka来讲,有两种方式:

1)一个topic对应一个partition和一个消费者,这样生产者的所有数据都发送到了一个partition(分区),保证了消息的消费顺序。但是这种内部单线程消费的方式,吞吐量太低,一般不会采用

2)写N个queue,生产者在写的时候,指定一个key,将具有相同key的数据都存储在同一个queue,然后对于N个线程,每个线程分别消费一个queue,这样就能保证顺序性

4. Kafka的高可用机制

Kafka 的高可用主要体现在两个方面,一个是集群,第二个是提供了复制机制:

集群:kafka集群指的是由多个broker实例组成,即使某一台机,也不耽误其他broker继续对外提供服务。创建一个topic可以划分为多个partition,每个partition可以存在于不同的broker上,每个 partition就放一部分数据,这就是天然的分布式消息队列。就是说一个topic的数据是分散放在多个机器上的,每个机器就放一部分数据。

复制机制:复制机制是可以保证kafka的高可用的,一个topic有多个分区,每个分区有多个副本,有一个leader,其余的是follower,副本存储在不同的broker中:所有的分区副本的内容是都是相同的,如果leader发生故障时,会自动将其中一个follower提升为leader,保证了系统的容错性、高可用性。每个 partition 的数据都会同步到其他机器上,形成自己的多个副本。然后所有 replica 会选举一个 leader 出来,生产和消费都跟这个 leader 打交道,然后其他 replica 就是 follower。写的时候,leader 会负责把数据同步到所有 follower 上去,读的时候就直接读 leader 上数据即可。这样假设某个broker宕机,这个broker上的partition在其他机器上都有副本,如果宕机的是leader的broker,follower将会选举一个新的leader。同时Kafka 会保证将一个 partition 的所有 replica 均匀分布在不同的机器上,进一步提高了容错性。

5. Kafka数据清理机制

Kafka中topic的数据存储在分区上,分区如果文件过大会分段存储segment,每个分段都在磁盘上以索引(xxxx.index)和日志文件(xxxx.log)的形式存储,这样分段的好处是,第一能够减少单个文件内容的大小,查找数据方便,第二方便kafka进行日志清理。

在kafka中提供了两个日志的清理策略:

  1. 根据消息的保留时间,当消息保存的时间超过了指定的时间,就会触发清理,默认是168小时(7天)
  2. 第二是根据topic存储的数据大小,当topic所占的日志文件大小大于一定的阈值,则开始删除最久的消息。这个默认是关闭的

这两个策略都可以通过kafka的broker中的配置文件进行设置。

6. Kafka发送数据的原理

首先创建一个main线程,其中包含生产者对象producer,构造send方法发送消息,消息首先经过一个拦截器,可以做一些对数据的处理,这个拦截器也可以选择直接略过,然后经过一个序列化器,对数据进行序列化。序列化器后是一个分区器。因为在main线程中是创建了一个双端队列RecordAccumulator的,其中包含很多数据分区,main线程也会将消息发送给这个双端队列,但是具体发送给这个队列中的哪一个分区,是由这个分区器计算得到结果再进行分发的。这个RecordAccumulator默认大小32m,生产者往里送数据默认是16k一批。数据存入这个双端队列后,sender线程用来拉取队列中的数据发送给broker。这里只有数据积累到batch.size之后,sender才会发送数据,默认是16K 。如果数据一直达不到这个batch.size,sender会等待linger.ms设置的时间,时间到了就会发送数据。发送的过程中,是以broker节点作为key,以发送的消息作为value进行传输。发送过程中,如果broker没有及时应答,最多缓存五个请求在内存中。如果反馈发送成功,那么就会清里sender中的发送请求和RecordAccumulator中的分区数据。如果反馈发送失败,就会重试,重试的次数默认是int的最大值。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值