Kafka经典面试题

线上问题rebalance

因集群架构变动导致的消费组内重平衡,如果kafka集内节点较多,比如数百个,那重平衡可能会耗时导致数分钟到数小时,此时kafka基本处于不可用状态,对kafka的TPS影响极大

产生的原因:

  • 组成员数量发生变化

  • 订阅主题数量发生变化

  • 订阅主题的分区数发生变化

    组成员崩溃和组成员主动离开是两个不同的场景。 因为在崩溃时成员并不会主动地告知coordinator此事,coordinator有可能需要一个完整的session.timeout周期(心跳周期)才能检测到这种崩溃,这必然会造成consumer的滞后。可以说离开组是主动地发起rebalance;而崩溃则是被动地发起rebalance。

成员1 Coordinator 成员2 Heartbeat(我是g1的成员C1,generation是2,hello) Heartbeat(hello,c1) Heartbeat(我是g1的成员C2,generation是2,hello) Heartbeat(hello,c2) Heartbeat(我是g1的成员C1,generation是2,hello) Heartbeat(c1,不好意思,你需要重新加入g1) JoinGroup(请求加入g1,这是我的订阅信息) JoinGroup(批准加入。你是c1,也是leader,现在generation是3,g1成员为c1,这些是订阅信息) SyncGroup(这是我的分配方案) SyncGroup(c1,你需要消费这些分区) 成员1 Coordinator 成员2

解决方案:

加大超时时间 session.timout.ms=6s
加大心跳频率 heartbeat.interval.ms=2s
增长推送间隔 max.poll.interval.ms=t+1 minutes

ZooKeeper 的作用

目前,Kafka 使用 ZooKeeper 存放集群元数据、成员管理、Controller 选举,以及其他一些管理类任务。之后,等 KIP-500 提案完成后,Kafka 将完全不再依赖于 ZooKeeper。

  • 存放元数据是指主题分区的所有数据都保存在 ZooKeeper 中,其他“人”都要与它保持对齐。
  • 成员管理是指 Broker 节点的注册、注销以及属性变更等 。
  • Controller 选举是指选举集群 Controller,包括但不限于主题删除、参数配置等。

一言以蔽之:KIP-500 ,是使用社区自研的基于 Raft 的共识算法,实现 Controller 自选举

同样是存储元数据,这几年基于Raft算法的etcd认可度越来越高

越来越多的系统开始用它保存关键数据。比如,秒杀系统经常用它保存各节点信息,以便控制消费 MQ 的服务数量。还有些业务系统的配置数据,也会通过 etcd 实时同步给业务系统的各节点,比如,秒杀管理后台会使用 etcd 将秒杀活动的配置数据实时同步给秒杀 API 服务各节点

Replica副本的作用

Kafka 只有 Leader 副本才能 对外提供读写服务,响应 Clients 端的请求。Follower 副本只是采用拉(PULL)的方 式,被动地同步 Leader 副本中的数据,并且在 Leader 副本所在的 Broker 宕机后,随时准备应聘 Leader 副本。

  • 自 Kafka 2.4 版本开始,社区可以通过配置参数,允许 Follower 副本有限度地提供读服务。
  • 之前确保一致性的主要手段是高水位机制, 但高水位值无法保证 Leader 连续变更场景下的数据一致性,因此,社区引入了 Leader Epoch 机制,来修复高水位值的弊端。

为什么不支持读写分离?

  • 自 Kafka 2.4 之后,Kafka 提供了有限度的读写分离。
  • 场景不适用。读写分离适用于那种读负载很大,而写操作相对不频繁的场景。
  • 同步机制。Kafka 采用 PULL 方式实现 Follower 的同步,同时复制延迟较大。

如何防止重复消费

  • 代码层面每次消费需提交offset
  • 通过Mysql的唯一键约束,结合Redis查看id是否被消费,存Redis可以直接使用set方法
  • 量大且允许误判的情况下,使用布隆过滤器也可以

如何保证数据不会丢失

  • 生产者生产消息可以通过comfirm配置ack=all解决
  • Broker同步过程中leader宕机可以通过配置ISR副本+重试解决
  • 消费者丢失可以关闭自动提交offset功能,系统处理完成时提交offset

如何保证顺序消费

  • 单 topic,单partition,单 consumer,单线程消费,吞吐量低,不推荐
  • 如只需保证单key有序,为每个key申请单独内存 queue,每个线程分别消费一个内存 queue 即可,这样就能保证单key(例如用户id、活动id)顺序性。

####【线上】如何解决积压消费

  • 修复consumer,使其具备消费能力,并且扩容N台
  • 写一个分发的程序,将Topic均匀分发到临时Topic中
  • 同时起N台consumer,消费不同的临时Topic

如何避免消息积压

  • 提高消费并行度
  • 批量消费
  • 减少组件IO的交互次数
  • 优先级消费
if (maxOffset - curOffset > 100000) {
    
    
  // TODO 消息堆积情况的优先处理逻辑
  // 未处理的消息可以选择丢弃或者打日志
  return ConsumeConcurrentlyStatus.CONSUME_SUCCESS;
}
// TODO 正常消费过程
return ConsumeConcurrentlyStatus.CONSUME_SUCCESS;

作者:我是hope啊
链接:https://juejin.cn/post/7062892826241007646
来源:稀土掘金
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

如何设计消息队列

需要支持快速水平扩容,broker+partition,partition放不同的机器上,增加机器时将数据根据topic做迁移,分布式需要考虑一致性、可用性、分区容错性

  • 一致性: 生产者的消息确认、消费者的幂等性、Broker的数据同步
  • 可用性: 数据如何保证不丢不重、数据如何持久化、持久化时如何读写
  • 分区容错: 采用何种选举机制、如何进行多副本同步
  • 海量数据: 如何解决消息积压、海量Topic性能下降

性能上,可以借鉴时间轮、零拷贝、IO多路复用、顺序读写、压缩批处理

猜你喜欢

转载自blog.csdn.net/zhw21w/article/details/129517642