Kafka

  1. Kafka是一个开源的高吞吐量的分布式消息中间件

    Kafka 能够在不牺牲性能的情况下处理大规模的数据流。它通过批量处理和零拷贝技术来提高吞吐量,有效地减少了磁盘和网络 I/O 的开销。

    Kafka 的设计基于分布式架构,集群中的数据被分割成多个分区,并分布在多个服务器节点上。分布式架构使 Kafka 具有高可用性和可扩展性,可以处理大量数据并且可以容易地扩展以适应不断增长的负载。

  2. 与RabbitMQ的区别

    • Kafka更适合处理大规模数据流实时分析,强调性能和扩展性。
    • RabbitMQ更适合企业级应用集成复杂的消息路由,强调灵活性和可靠性。
  3. Kafka为什么这么快

    • 顺序 I/O 与零拷贝(磁盘IO性能)(40%)
      • Kafka 的消息追加到日志文件时,采用顺序写入磁盘。比随机写入快 10-100 倍
      • 将磁盘文件数据直接从 Page Cache 拷贝到网卡缓冲区,绕过用户空间,减少 CPU 拷贝和上下文切换。
    • 批量处理(减少网络、磁盘、系统调用开销)(30%)
      • 生产者将多条消息合并为 Batch,再发送到 Broker。减少网络请求次数和 TCP 包数量,提高网络利用率。
      • 消费者通过1次拉取多条消息,减少网络往返
      • Broker 批量刷盘,消息先写入 Page Cache,由内核线程批量刷盘。
    • 分区(Partition)与并行处理(20%)
      • 分区设计使得 Kafka 的吞吐可以线性扩展,突破单机性能瓶颈。
  4. Pull 拉模式:消费者通过 API 向 Broker 发起拉取请求。如果队列中有消息,Broker 返回一批消息(可能少于请求数量)。如果队列为空,Broker 等待直到超时或新消息到达(长轮询机制)。消费者处理消息,并提交偏移量(Offset)确认消费进度。继续下一轮拉取。

    将控制权交给消费者,通过主动拉取、灵活管理消费进度,实现高效、可靠的消息消费。消费者可以重置 Offset,重新消费历史消息(如 Kafka 的 seek())。

  5. 消息队列通常支持两种主要模式:点对点(Point-to-Point)和发布-订阅(Publish-Subscribe)。

    • 在点对点模式下,消息被发送到一个队列(Queue)中,并且只有一个消费者可以接收和处理该消息。

      消息生产者(发送者)将消息发送到队列中,然后消息消费者(接收者)从队列中接收并处理消息。一旦消息被消费者接收并处理,它将从队列中删除。

    • 在发布-订阅模式下,消息被发送到一个主题(Topic)中,多个消费者可以订阅该主题并接收其中的消息。

      消息生产者将消息发布到一个主题中,然后所有订阅该主题的消费者都会接收到该消息的副本,并且每个消费者都可以独立地处理这些消息。

      消费者消费数据之后,不会删除数据。

  6. Partition:分区,为了实现扩展性,一个topic可以分布在多个broker上,一个topic可以分为多个partition,每个partition都是一个有序的队列。partition中的每条消息都会被分配一个有序的id(offset)。kafka只保证同一个partition中的消息顺序,不保证一个topic的整体(多个partition之间)的顺序。生产者和消费者使用时可以指定topic中的具体partition。

  7. 早期版本的kafka用zookeeper做meta信息存储,consumer的消费状态,group的管理以及 offset的值。考虑到zk本身的一些因素以及整个架构较大概率存在单点问题,新版本中逐渐弱化了zookeeper的作用。新的consumer使用了kafka内部的group coordination协议,也减少了对zookeeper的依赖,

    但是broker依然依赖于ZK,zookeeper 在kafka中还用来选举controller 和 检测broker是否存活等等。

  8. 发送消息的分区策略有哪些

    轮询策略,随机策略,和按键保存策略。其中轮询策略是默认的分区策略。

    按键保存策略,就是当生产者发送数据的时候,可以指定一个key,计算这个key的hashCode值,按照hashCode的值对不同消息进行存储。

    上面有说到一个场景,那就是要顺序发送消息到kafka。前面提到的方案是让所有数据存储到一个分区中,但其实更好的做法,就是使用这种按键保存策略。

    让需要顺序存储的数据都指定相同的键,而不需要顺序存储的数据指定不同的键,这样一来,即实现了顺序存储的需求,又能够享受到kafka多分区的优势。

    img

  9. kafka可靠性

    broker:topic分区副本

    producer:producer在发送数据时可以将多个请求进行合并后异步发送。producer异常中断,buffer中的数据将丢失。producer客户端内存不足,如果采取的策略是丢弃消息(另一种策略是block阻塞),消息也会丢失。消息产生(异步)过快,导致挂起线程过多,内存不足,导致程序崩溃,消息丢失。

    consumer:消费方式主要分为两种,自动提交offset,手动提交offset。Consumer自动提交机制是根据一定的时间间隔,将收到的消息进行commit。可能存在消费过程未成功,commit消息就已经提交,此时就会出现消息丢失。

  10. 为什么kafka不支持读写分离

数据一致性问题,数据从主节点转到从节点前必然会有一个延时的时间窗口,这个时间 窗口会导致主从节点之间的数据不一致。

延时问题:在 Kafka 中,主从同步会比 Redis 更加耗时,它需要经历网络→主节点内存→主节点磁盘→网络→从节 点内存→从节点磁盘这几个阶段。对延时敏感的应用而言,主写从读的功能并不太适用。

  1. 脑裂问题:比如,某个controller由于GC而被认为已经挂掉,并选择了一个新的controller。在GC的情况下,在最初的controller眼中,并没有改变任何东西,该Broker甚至不知道它已经暂停了。因此,它将继续充当当前controller,这是分布式系统中的常见情况,称为脑裂。

    Kafka是通过使用epoch number(纪元编号,也称为隔离令牌)来完成的。epoch number只是单调递增的数字,第一次选出Controller时,epoch number值为1,如果再次选出新的Controller,则epoch number将为2,依次单调递增。

    每个新选出的controller通过Zookeeper 的条件递增操作获得一个全新的、数值更大的epoch number 。其他Broker 在知道当前epoch number 后,如果收到由controller发出的包含较旧(较小)epoch number的消息,就会忽略它们,即Broker根据最大的epoch number来区分当前最新的controller。

posted @ 2025-09-28 16:05  疯啦吧你  阅读(26)  评论(0)    收藏  举报