Kafka 常见面试题(二)

Consumer位移自动提交时机

Kafka consumer不需要手动提交offset,可以自动提交。

// 是否自动提交偏移量
props.put(ConsumerConfig.ENABLE_AUTO_COMMIT_CONFIG, "true");
// 自动提交偏移量
props.put(ConsumerConfig.AUTO_COMMIT_INTERVAL_MS_CONFIG, "5000");  // 默认为5000ms
  1. Consumer poll的时候(异步提交)
    并不是每次poll都会调用自动提交位移,而是有前提条件:now>lastNow+auto.commit.interval.ms
    假如 auto.commit.interval.ms 设置为 3000,但是检查时间间隔是否过了 3 秒是由 poll 方法去触发的,所以只要在记录还没处理完之前我们没有主动去调用 poll 方法,就算时间间隔到了,也不会去自动提交。
private void maybeAutoCommitOffsetsAsync(long now) {
    if (autoCommitEnabled) {
        if (coordinatorUnknown()) {
            this.nextAutoCommitDeadline = now + retryBackoffMs;
        // 并不是每次poll的时候会调用自动提交位移
        // 条件为:now > oldNow + auto.commit.interval.ms
        // 触发条件和用户设置的auto.commit.interval.ms有关,设置时间长
        // 则触发的次数少,设置时间短则触发次数多
        } else if (now >= nextAutoCommitDeadline) {
            this.nextAutoCommitDeadline = now + autoCommitIntervalMs;
            doAutoCommitOffsetsAsync();
        }
    }
}
  1. Consumer手动指定partition(异步提交)
    消费者在消费过程中收到KafkaConsumer#assign指令,此时订阅的分区可能发生变化了,所以需要将之前的分区offset信息提交上去
  public void maybeAutoCommitOffsetsNow() {
        // 必须要设置自动提交且已经和服务端的协调者建立连接
        // 1、如果消费者还没有开始消费指定分区是不会触发自动提交位移
        // 2、如果消费者在消费的过程中收到一条KafkaConsumer#assign的指令,此时消
        //    费订阅的分区极有可能发生改变,所以一定要将之前订阅的分区相关信息提交
        //    给服务端的协调者。
        if (autoCommitEnabled && !coordinatorUnknown())
            doAutoCommitOffsetsAsync();
        }
    }
  1. Consumer以Group形式启动,加入时rebalance之前(同步提交)
    因为Rebalance涉及到分区可能会改变
  2. Consumer关闭(同步提交)
    关闭时肯定是需要提交offset的。

Consumer消费过慢会有什么问题

如果Consumer消费过慢是有可能触发rebalance的,这批消费会被重新分配到其他消费者,然后新的Consumer会再次消费过慢,再次rebalance,看到如下信息即rebalance了:

Commit cannot be completed since the group has already rebalanced and assigned the partitions to another member. This means that the time between subsequent calls to poll() was longer than the configured max.poll.interval.ms, which typically implies that the poll loop is spending too much time message processing. You can address this either by increasing the session timeout or by reducing the maximum size of batches returned in poll() with max.poll.records.

在Kafka 0.10.1.0之后的版本中,影响rebalance的参数有三个:

  1. session.timeout.ms
    这个参数定义了broker在多久没有收到consumer的心跳请求后触发Rebalance,默认是10s。在0.10.1.0之前的版本中,由于心跳请求是包含在poll()中,因此如果在poll()某批消息后消费特别慢耗时过长,就会导致心跳超时触发Rebalance,在0.10.1.0及之后的版本中解决了这个问题,心跳请求会在单独的线程中发送,因此就不会出现因为消息处理过长而发不出心跳的问题了。
  2. max.poll.interval.ms
    这个参数定义了两次poll()之间的最大间隔,默认是5m,超过这个间隔会触发Rebalance,在多数情况下,这种情况是导致Rebalance的主要问题点,也就是业务处理的时间过长。
  3. max.poll.records
    定义了每次poll()方法每次最多返回的条数,默认是500,如果不足500条消息也会返回500条,如果业务逻辑在5m内无法处理500条消息,那么就就触发Rebalance,这批消息又会被分配给其他的Consumer。

因此,在实际生产环境,要评估每条消息的处理时间,一般会留20%的冗余空间,同时覆盖默认的max.poll.records参数。在spring-kafka中对应的配置是max-poll-records。对于消息处理比较重的操作,建议把这个值改到50以下会保险一些。

Kafka为什么这么快

  1. 顺序读写
  2. Page Cache:利用了操作系统本身的Page Cache,而不是JVM空间内存
  3. 零拷贝:直接将数据从内核空间的读缓冲区直接拷贝到内核空间的socket缓冲区
  4. 分区分段+索引:采用topic分类存储,topic的数据又按partition存储到不同的节点,kafka中的消息实际上是分布式存储在一个个小的segment中的,每次文件操作也是直接操作的segment,Kafka为分段后的数据文件建立了索引文件
  5. 批量读写
  6. 批量压缩

Kafka控制器怎么选举的

依赖于Zookeeper,成功选举为Controller的broker会在Zookeeper下创建/controller临时节点
每个broker在启动的时候都会尝试读取/controller节点的brokerid的值:

  1. 如果读取的brokerid不为-1,表示已经有其他的broker节点被选举为controller
  2. 如果不存在/controller节点,那么就会尝试去创建,创建成功的broker就是controller

每个broker都会在内存中保存当前controller的brokerid,标识位activeControllerId
Zookeeper中还有一个和controller有挂的/controller_epoch节点,持久化节点,用于记录控制器发送变更的次数,初始化为1,当controller发生变化时则+1,每个与controller交互的请求都会带上controller_epoch这个字段:

  1. 如果请求的controller_epoch小于内存中的epoch值,那么认为当前请求是过期controller发送的请求,无效请求
  2. 如果请求的controller_epoch大于内存中的epoch,那么证明有新的controller当选了

Controller作用是什么

负责管理整个集群中所有分区和副本的状态

  1. 当leader副本出现故障时,有Controller负责为该分区选举新的Leader
  2. 当检测到某分区的ISR集合发送变化时,由Controller负责同志所有broker更新其元数据信息
  3. 当为某个topic增加分区时,由controller负责分区的重新分配

Kafka支持读写分离吗

不支持
读写分离有两大缺点:数据不一致,延时问题

Consumer和topic的分区分配策略

  1. RangeAssignor
    按照消费者总数和分区总数进行整除获取一个跨度,根据跨度平均分配,对于每个topic,先将消费者根据名称顺序排列,然后为每个消费者划分固定的跨度,如果不够平均分配,那排序靠前的会多分配一个分区
  2. RoundRobinAssignor
    按照消费者及topic的分区字典排序,然后通过轮询的方式分配给每个消费者
  3. StickAssignor
    分区分配尽可能均匀
    分区分配尽可能与上次的分配保持相同

https://zhuanlan.zhihu.com/p/123361451
https://www.jianshu.com/p/c19c0e61c88a

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值