当前位置: 首页 > article >正文

【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,这样就可以接收这个节点的变更通知。通过这样的方式来保证节点只有一个控制器。
    image

变更控制器

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

新控制器 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%数据包含脏记录时进行压实。
  • 每个日志片段分为两个部分
    • 干净的部分:被压实过的消息,每个键只有一个对应得值,是上一次压实保留下来得
    • 浑浊部分:上一次压实之后写入得
      image

http://www.kler.cn/a/594983.html

相关文章:

  • C# MethodBase 类使用详解
  • acwing1295. X的因子链
  • CMake 函数和宏
  • 嵌入式软件单元测试的必要性、核心方法及工具深度解析
  • 在 Windows 系统下,将 FFmpeg 编译为 .so 文件
  • Touch Diver:Weart为XR和机器人遥操作专属设计的触觉反馈动捕手套
  • 对敏捷研发的反思,是否真是灵丹妙药?
  • HTTPS 加密过程详解
  • 【SpringBoot】MorningBox小程序的完整后端接口文档
  • 3.20【L】algorithm
  • 「Java EE开发指南」用MyEclipse开发EJB 3无状态会话Bean(一)
  • HTML5响应式使用css媒体查询
  • teaming技术
  • Python深浅拷贝
  • 【QA】装饰模式在Qt中有哪些运用?
  • 服务器——报错解决:移动文件时,bash: /usr/bin/mv: Argument list too long
  • Java基础关键_027_IO流(五)
  • 软考-软件设计师-程序设计语言
  • 数据结构——顺序栈seq_stack
  • 力扣刷题——143.重排链表