broker组件(转Apache kafka实战)

broker是Apache Kafka 最重要的组件, Kafka broker 负责持久化 producer 端发送的消息,同时还为 consumer 端提供消息。
broker 的各种设计思想,具体分为以下6个方面:

一、消息设计

VO版本

主要指 Kafka 0.10.0 之前的版本,是 Kafka 最早的消息版本,其消息格式如图示。 在这里插入图片描述
其中,各个字段的含义如下。

  • CRC 校验码: 4字节的 CRC 校验码,用于确保消息在传输过程中不会被恶意篡改
  • magic :单字节的版本号 V0 版本 magic=0, Vl 版本 magic=l, V2 版本 magic=2
  • attribute :单字节属性宇段,目前只使用低3位表示消息的压缩类型
  • key 长度字段: 4字节的消息 key 长度信息。若未指定 key ,则给该字段赋值为-1
  • key 值:消息 key ,长度由上面的“key 长度字段”值指定。如果“key 长度字段”值是-1 ,则无 key ,消息没有该字段。
  • value 长度字段: 4字节的消息长度。若未指定 value ,则给该字段赋值为-1
  • value 值:消息 value ,长度由上面的“value 长度字段”值指定。如果“ value 长度字段”值是-1,则无 value ,消息没有该字段。

V1版本

随着 Kafka 功能的不断演进,人们日益发现 V1版本消息在实际使用过程中存在着一些显著的弊端,比如:

  • 由于没有消息的时间信息, Kafka 定期删除过期日志只能依靠日志段文件的“最近修改时间”,但这个时间极易受到外部操作的干扰。举一个例子,若不小心对日志段文件执行了 UNIX touch 命令,该日志文件的最近修改时间就被更新了。 旦这个时间被“破坏”或者更改, Kafka 将无法对哪些消息过期做出正确判断。
  • 很多流式处理框架都需要消息保存时间信息以便对消息执行时间窗口等聚合操作。

主要的变化就是在消息中加入了时间戳宇段,如图所示。
在这里插入图片描述
V2版本

依然分为消息和消息集合两个维度,只不过消息集合的提法被消息批次所取代。
在这里插入图片描述

二、集群管理

Kafka 是分布式的消息引擎集群环境,它支持自动化的服务发现与成员管理。Kafka 是依赖 Apache ZooKeeper 实现的
。每当一个broker 启动时,它会将自己注册到 ZooKeeper 下的一个节点 。

broker向ZooKeeper中注册的信息以JSON 格式保存,其中包括的信息如下:

  • listener_ security _protocol map :此值指定了该 broker 与外界通信所用的安全协议类型。Kafka 当前支持 broker 使用不同的安全协议类型与 clients 和其他 broker 通信。比如,用户可以配置成与公网 clients 通信使用 SSL 传输数据,而与内网其他 broker 通信使用PLAINTEXT 。即 broker 与外界切数据交互都以明码文本的方式传输。
  • endpoints :指定 broker 的服务 endpoint 列表,每个 endpoint 指明了传输协议类型、broker 主机名和端口信息。既然是列表,说明 endpiont 可以配置多个,每种协议类型都可以配置 个对应的 endpoint ,只是端口号不能冲突。
  • rack :指定 broker 机架信息 Hadoop 机架感知原理类似,若设置了机架信息,Kafka 在分配副本时会考虑把某个分区的多个副本分配在多个机架上。这样即使某个机架上的 broker 全部崩溃,也能保证其他机架上的副本可以正常工作。
  • jmx_port: broker 阻监控端口,需要在启动 broker 前设置 JMX_PORT 环境变量设置 JMX 端口后各种支持凡仪的监控框架(如 Zabbix 等)才可以实时获取 Kafka供的各种 broker 端监控指标。

三、 副本与 ISR 设计

一个Kafka 分区本质上就是一个备份日志,即利用多份相同的备份共同提供冗余机制来保持系统高可用性,这些备份在 Kafka中被称为副本( replica)。 Kafka 把分区的所有副本均匀地分配到所有 broker 上,并从这些副本中挑选一个作为 leader 副本对外提供服务,而其他副本被称为 follower 副本,只能被动地向 leader 副本请求数据,从而保持与 leader副本的同步。
假如 leader 副本永远工作正常,那么其实不需要 follower 副本。但现实总是残酷的,Kafka leader 副本所在的
broker 可能因为各种各样的原因而随时窑机。一旦发生这种情况,follower 副本会竞相争夺成为新 leader 的权力。显然不是所有follower 都有资格去竞选 leader。 follower 被动地向 leader 请求数据,对于那些落后 leader 进度太多的follower们是没有资格竞选 leader 的,毕竟它们手中握有的数据太旧了,如果允许它们成为 leader, 会造成数据丢失,而这对clients 而言是灾难性的 。鉴于这个原因, Kafka 引入了 ISR 的概念。 所谓 ISR ,就是 Kafka集群动态维护的一组同步副本集合( in-sync replicas), 每个 topic分区都有自己的 ISR 列表, ISR中的所有副本都与 leader 保持同步状态。值得注意的是, leader副本总是包含在 ISR 中的,只有 ISR 中的副本才有资格被选举为 leader 。而producer 写入的Kafka 消息只有被 ISR中的所有副本都接收到,才被视为“己提交”状态 由此可见,若ISR 中有N个副本,那么该分区最多可以忍受N-1个副本崩溃而不丢失己提交消息。

ISR 设计

  1. 0.9.0.0 版本之前
    0.9.0.0 版本之前, Kafka 提供了一个参数 replica.lag.max.messages ,用于控制 follower 副本落后 leader 副本的消息数。一旦超过这个消息数,则视为该 follower 为“不同步”状态,从而需要被 Kafka “踢出” ISR。
  2. 0.9.0.0 版本之后
    自0.9 .0 .0 版本之后, Kafka 去掉了之前的 replica. lag.max.messages 参数,改用统一的参数同时检测由于慢以及进程卡壳而导致的滞后 (lagging )一一即 follower 副本落后 leader 副本的时间间隔。这个唯一的参数就是replica.lag.time.max.ms ,默认值是 10秒。对于“请求速度追不上”的情况,检测机制也发生了变化一一如果 follower 副本落后 leader 的时间持续性地超过了这个参数值,那么该 follower 副本就是“不同步”的。这样即使出现刚刚提到的producer 瞬时峰值流量,只要 follower 不是持续性落后,它就不会反复地在 ISR 中移进、移出。

四、通信协议

协议设计

Kafka通信协议是基于 TCP 之上的二进制协议,这套协议提供的 API 表现为服务于不同功能的多种请求request类型以及对应的响应 response 。所有类型的请求和响应都是结构化的,由不同的初始类型构成 Kafka 使用这组协议完成各个功能的实现。

请求/响应结构
Kafka 协议提供的所有请求及其响应的结构体都是由固定格式组成的,它们统一构建于多种初始类型(primitive types )之上。这些初始类型如下

  • 固定长度初始类型:包括 int8 intl6 int32 int64 ,分别表示有符号的单字节整数、双字节整数、4字节整数和8字节整数。
  • 可变长度初始类型:包括 bytes和string,由一个有符号整数N加上后续的N字节组成。N表示它们的内容,若是-1,则表示内容为空。其中 string 类型使用 intl6 来保存 N;bytes 使用 int32 来保存。
  • 数组:用于处理结构体之类重复性数据结构。它们总是被编码成一个 int32 类型的整数N以及后续的N字节。同样,N表示该数组的长度信息,而具体到里面的元素可以是其他的初始类型。在下面的请求结构体部分,我们使用[Array]的方式来表示数组。

所有的请求和响应都具有统一的格式,即 Size + Request/Response ,其中的 Size是int32表示的整数,表征了该请求或响应的长度信息。

请求又可划分成请求头部和请求体,请求体的格式因请求类型的不同而变化,但请求头部的结构是固定的一一它由以下4个字段构成。

  • api key :请求类型,以 intl6 整数表示。
  • api_version :请求版本号,以 int16 整数表示。
  • correlation_id :与对应响应的关联号,实际中用于关联 response request ,方便用调试和排错。该字段以 int32 整数表示。
  • client id :表示发出此请求的 client ID 。实际场景中用于区分集群上不同 clients 发送的请求。该字段是一个非空字符串。

同理,响应也可划分成响应头部和响应体,响应体的格式因其对应的请求类型的不同而变
化,但响应头部的结构是固定的一一它只有下面的这个字段。

  • correlation id :该字段值就是上面请求头部中的 correlation id 。有了该字段,用户就能够知道该响应对应于哪个请求了。

常见请求类型

  • PRODUCE 请求
    这是编号为0的请求,即 api_key =0 ,也就是 Kafka 信协议中的第一个请求类型。它实现消息的生产。 clients broker 发送 PRODUCE 请求并期待 broker 端返回响应表明消息生产是否成功。
  • FETCH 请求
    FETCH 请求是编号为1 的请求,即 api_key = 1。它服务于消费消息 ,既包括 clients broker 发送的 FETCH 请求,也包括分区 follower 副本发送 leader 副本的 FETCH 请求。
  • METADATA 请求
    clients向broker 发送 METADATA 请求以获取指定 topic 的元数据信息,其格式为[topics] + allow_auto_topic_ creation。

请求处理流程

五、controller 设计

在一个Kafka 集群中,某个 broker会被选举出来承担特殊的角色,即控制器(controller)。顾名思义,引入controller就是用来管理和协调 Kafka 集群的。具体来说,就是管理集群中所有分区的状态并执行相应的管理操作。

每个Kafka集群任意时刻都只能有一个controller。当集群启动时,所有 broker 都会参与controller竞选,但最终只能由一个broker 胜出 。一旦 controller 在某个时刻崩溃,集群中剩余的 broker会立刻得到通知,然后开启新一轮的controller 选举。新选举出来的 controller 将承担起之前controller的所有工作。

controller 管理状态
controller 维护的状态分为两类:每台 broker 上的分区副本和每个分区的 leader副本信息。从维度上看,这些状态又可分为副本状态和分区状态。 controller 为了维护这两个状态专门引入了两个状态机,分别管理副本状态和分区状态。

controller 职责
对集群状态的维护只是controller 保持运行状态一致性的一个基本要素,但却不是controller 的职责所在。应该这样说,如果保持 controller 持续稳定地对外提供服务,就必须要controller 妥善地保存这些状态。实际上,controller 的职责相当多,包括如下:

  • 更新集群元数据信息
  • 创建 topic
  • 删除 topic
  • 分区重分配
  • preferred leader 副本选举
  • topic 分区扩展
  • broker 加入集群
  • broker 崩溃
  • 受控关闭
  • controller leader 选举

controller broker 间的通信
controller 启动时会为集群中所有 broker 创建一个专属的 Socket 连接(也包括controller 所在的 broker) 这就是说,若 Kafka 集群有 100 broker 机器,那么 controller会创建 100 Socket 连接。
controller 绝大多数的功能都是依Zookeeper 来完成的,但只有ColledShutdownRequest这个请求是 broker与controller 直接进行交互完成的。

controller 组件

六、broker 请求处理

Reactor 模式
Kafka broker 处理请求的模式就是 Reactor 设计模式(生产者-消费者)
Reactor 模式中有很两个很重要的组件 acceptor 线程和 processor 线程。acceptor 线程实时地监听外部数据源发送过来的事件,并执行分发任务。 processor 线程执行时间处理逻辑并将处理结果发送给 client。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值