【Kafka】深入了解Kafka

集群的成员关系

Kafka使用Zookeeper维护集群的成员信息

  • 每一个broker都有一个唯一的标识,这个标识可以在配置文件中指定,也可以自动生成。
  • broker在启动时通过创建Zookeeper的临时节点 把自己的ID注册到Zookeeper中。broker、控制器和其他一些动态系统工具 会订阅Zookeeper的 /brokers/ids 路径;当有broker加入或退出集群时,会收到通知。
  • 当试图启动另一个具有相同ID的broker时,会收到错误信息。

控制器

控制器也是一个broker,除了提供一般broker功能外,还负责选举分区首领

创建控制器

  • 集群中第一个启动的broker会通过Zookeeper创建一个/controller的临时节点让自己成为控制器;
  • Zookeeper会为控制器分配一个epoch
  • 其他broker在启动时,也会尝试创建,但是因为已经存在他们会收到"节点已存在"异常;
  • 然后在控制器节点上创建Zookeeper watch,这样就可以接收这个节点的变更通知。通过这样的方式来保证节点只有一个控制器。

变更控制器

  • 控制器关闭或者与Zookeeper断开连接,这个临时节点会消失;
  • 当其他节点收到控制器节点消失的通知时,会尝试创建/controller的临时节点成为控制节点;
  • 其他未创建成功的broker会在新的控制节点上创建Zookeeper watch
  • 新的控制器节点由Zookeeper分配一个数值更大的epoch。这样做的目的是为了杜绝之前离线的控制器重新上线,并且发送消息,如果broker接收到消息的epoch小于监听的则会忽略当前消息。

新控制器 KRaft

用基于Raft的控制器替换基于Zookeeper的控制器。

集群即可以使用基于Zookeeper的传统控制器,也可以使用KRaft

为什么替换控制器

  • 元数据是同步写入Zookeeper的,但是异步发送给broker的,Zookeeper的接收更新也是异步的,会导致broker、控制器和Zookeeper之间元数据不一致的情况
  • 控制器在重新启动时需要从Zookeeper读取所有的broker和分区元数据,再将他们发给所有broker,随着分区和broker的争夺,重启控制器会变慢。
  • 元数据所有权架构不够好,有些操作通过控制器、有些通过broker、有些通过Zookeeper来完成
  • 使用Kafka需要对Zookeeper有一定了解,学习成本较高

Zookeeper主要功能

  • 用于选举控制器
  • 保存集群元数据(broker、配置、主题、分区和副本)

KRaft

  • 新架构中控制器节点形成了一个Raft仲裁,管理元数据事件日志,这个日志包含了集群元数据的每一个变更,原先保存在Zookeeper中的所有东西(主题、分区、ISR、配置等)都保存在这个日志中。

  • 涉及直接与Zookeeper通信的客户端和broker操作都通过控制器来路由,以达到无缝迁移。

  • 使用Raft算法,控制节点可以在不依赖外部系统情况下选举首领,首领节点被称为主控制器,负责处理来自所有broker的RPC的调用,跟随者控制器从主控制器复制数据,并会作为主控制器的热备,

  • 其他broker通过API从主控制器获取更新,而不是等待通知。broker将自己注册到控制器仲裁上,在注销前会一直保持注册状态。

复制

复制是Kafka架构核心的一部分,之所以这么重要,是因为他可以在个别节点失效时仍能保证Kafka的可用性和持久性。

Kafka中每个主题有若干分区,每个分区可以有多个副本,副本均匀的分布在多个broker中。

副本有两种类型

  • 首领副本:每个分区都有一个首领副本,为了保证一致性,所有生产者的请求都会经过这个副本。客户端可以从首领副本或者跟随者副本读取数据
  • 跟随者副本:除了首领副本以外都是跟随者副本。没特别指定,跟随者副本不处理来自客户端的请求,主要任务是从首领副本复制消息,保持与首领一致的状态。

请求的处理

客户端持有集群的元数据缓存,元数据中包含了客户端感兴趣的主题清单以及主题包含的分区、副本、首领等,一般情况下客户端会直接向目标broker发送生产请求和获取请求。

请求分类

  • 生产请求
  • 获取请求
  • 管理请求

生产请求

生产者发送的请求,包含客户端要写入broker的消息

borker在接收到生产请求时会做一些验证

  • 发送数据的用户是否有写入权限
  • 请求中acks参数是否有效
  • 如果acks=all是否足够多的同步副本保证消息已经写入
    消息写入分区首领后,broker会检查acks参数,等到所有的都完成后,会返回响应给客户端。
    获取请求

消费者和跟随者副本发送的请求,用于从broker读取消息。

broker接收到获取请求时会做一些校验

  • 请求指定的偏移量是否存在
    客户端读取消息时,Kafka使用零复制 技术向客户端发送消息。也就是说Kafka会直接把消息从文件里发送到网路通道,不经过任何缓冲区。
    客户端能读取的消息是已经被写入所有同步副本的消息;部分没有完全同步给所有副本的消息是不会发送给消费者的。

管理请求

管理客户端发送的请求,用于执行元数据操作,比如创建和删除topic

存储

分层存储

  • 本次存储:与当前存储一致,保存在broker机器上
    • 优势:响应快
    • 劣势:成本高、数据保留时间短
  • 远程存储:利用HDFS、S3等存储系统来存储日志信息
    • 优势:成本低于本地存储、数据可保留较长时间
    • 劣势:响应较慢

文件管理

数据保留是Kafka的一个重要概念

  • Kafka中一个分区会分为若干片段
  • 默认每个片段包含1GB或者1周的数据,触发任意上限,会关闭当前文件,重新打开一个文件
  • 正在写入的片段叫做活动片段,活动片段不会被删除。

压实

保留每个键的最新有效数据,同时清理历史冗余的数据。

  • 保留最新值:对于每条消息,如果指定了 Key,Kafka 会为每个 Key 保留最后一个写入的 Value(最新状态)。
  • 删除冗余记录:所有旧版本的 Key-Value 对会被标记为可删除(逻辑删除),但物理删除会在后台异步完成。
  • 非键消息的保留:没有 Key 的消息(或 Key 为 null 的消息)不会被压实,仍然遵循基于时间或大小的保留策略(例如 7 天后删除)。

什么时候压实主题

  • 通过log.cleaner.enabled参数启动压实线程,线程会选择浑浊率最高的分区来压实。
  • 默认情况下会在主题中有50%数据包含脏记录时进行压实。
  • 每个日志片段分为两个部分
    • 干净的部分:被压实过的消息,每个键只有一个对应得值,是上一次压实保留下来得
    • 浑浊部分 :上一次压实之后写入得
相关推荐
学习中的阿陈14 分钟前
Hadoop伪分布式环境配置
大数据·hadoop·分布式
CesareCheung32 分钟前
JMeter分布式压力测试
分布式·jmeter·压力测试
thginWalker1 小时前
面试鸭Java八股之Kafka
kafka
失散132 小时前
分布式专题——10.5 ShardingSphere的CosID主键生成框架
java·分布式·架构·分库分表·shadingsphere
winfield8213 小时前
Kafka 线上问题排查完整手册
kafka
Cxzzzzzzzzzz6 小时前
RabbitMQ 在实际开发中的应用场景与实现方案
分布式·rabbitmq
在未来等你6 小时前
Kafka面试精讲 Day 16:生产者性能优化策略
大数据·分布式·面试·kafka·消息队列
王大帅の王同学6 小时前
Thinkphp6接入讯飞星火大模型Spark Lite完全免费的API
大数据·分布式·spark
一氧化二氢.h8 小时前
通俗解释redis高级:redis持久化(RDB持久化、AOF持久化)、redis主从、redis哨兵、redis分片集群
redis·分布式·缓存
爱睡觉的圈圈12 小时前
分布式IP代理集群架构与智能调度系统
分布式·tcp/ip·架构