Kafka 基础知识
Kafka 是一个分布式流式处理平台。
流平台具有三个关键功能:
- 消息队列:发布和订阅消息流,这个功能类似于消息队列,这也是 Kafka 也被归类为消息队列的原因。
- 容错的持久方式存储记录消息流: Kafka 会把消息持久化到磁盘,有效避免了消息丢失的风险·。
- 流式处理平台: 在消息发布的时候进行处理,Kafka 提供了一个完整的流式处理类库。
Kafka 主要有两大应用场景:
- 消息队列 :建立实时流数据管道,以可靠地在系统或应用程序之间获取数据。
- 数据处理: 构建实时的流数据处理程序来转换或处理数据流。
关于 Kafka 几个非常重要的概念:
- Kafka 将记录流(流数据)存储在
topic
中。 - 每个记录由一个键、一个值、一个时间戳组成。
Kafka 组件
在深入了解 Kafka 之前,您必须了解主要术语,例如主题、代理、生产者和消费者。下图说明了主要术语,表格详细描述了图表组件。
在上图中,一个主题配置为三个分区。分区 1 有两个偏移因子 0 和 1。分区 2 有四个偏移因子 0、1、2 和 3。分区 3 有一个偏移因子 0。副本的 id 与托管它的服务器的 id 相同。
假设主题的复制因子设置为 3,那么 Kafka 将为每个分区创建 3 个相同的副本,并将它们放置在集群中,以供所有操作使用。为了平衡集群中的负载,每个代理都会存储一个或多个分区。多个生产者和消费者可以同时发布和检索消息。
序号 | 组件 | 描述 |
---|---|---|
1 | 主题 | 属于特定类别的消息流称为主题。数据存储在主题中。主题被分成多个分区。对于每个主题,Kafka 至少保留一个分区。每个分区都包含按不可变顺序排列的消息。分区实现为一组大小相同的段文件。 |
2 | 分区 | 主题可能有许多分区,因此它可以处理任意数量的数据。 |
3 | 分区偏移 | 每个分区消息都有一个唯一的序列 ID,称为偏移量。 |
4 | 分区副本 | 副本只不过是分区的备份。副本永远不会读取或写入数据。它们用于防止数据丢失。 |
5 | 代理 | 代理是负责维护已发布数据的简单系统。每个代理可能对每个主题有零个或多个分区。假设,如果一个主题中有 N 个分区,并且有 N 个代理,则每个代理将有一个分区。假设一个主题中有 N 个分区,且有超过 N 个代理(n + m),则第一个 N 代理将有一个分区,而下一个 M 代理将没有针对该特定主题的任何分区。假设一个主题中有 N 个分区,而 Broker 数量少于 N 个(n - m),则每个 Broker 之间将共享一个或多个分区。由于 Broker 之间的负载分配不均,因此不建议采用此方案。 |
6 | Kafka 集群 | 拥有多个 代理 的 Kafka 称为 Kafka 集群。Kafka 集群可以在不停机的情况下进行扩展。这些集群用于管理消息数据的持久性和复制。 |
7 | 生产者 | 生产者是向一个或多个 Kafka 主题发布消息的人。生产者将数据发送到 Kafka 代理。每次生产者向代理发布消息时,代理都会将消息附加到最后一个段文件。实际上,该消息将附加到分区。生产者还可以将消息发送到他们选择的分区。 |
8 | 消费者 | 消费者从代理读取数据。消费者订阅一个或多个主题,并通过从代理提取数据来使用已发布的消息。 |
9 | 领导者 | Leader是负责给定分区的所有读写的节点。每个分区都有一台服务器充当 Leader。 |
10 | 追随者 | 遵循领导者指令的节点称为追随者。如果领导者失败,追随者之一将自动成为新的领导者。追随者充当普通消费者,提取消息并更新自己的数据存储。 |
一个 Kafka 集群有多个 Broker,一个 Broker 可以有多个 Topic,一个 Topic 可以有多个 Partition,一个 Partition 可以有多个副本,并且同一 Topic 下的 Partition 可以分布在不同的 Broker 上,这也就表明一个 Topic 可以横跨多个 Broker 。
Partition 中的多个副本之间会有一个叫做 leader 的家伙,其他副本称为 follower。我们发送的消息会被发送到 leader 副本,然后 follower 副本才能从 leader 副本中拉取消息进行同步。
生产者和消费者只与 leader 副本交互。你可以理解为其他副本只是 leader 副本的拷贝,它们的存在只是为了保证消息存储的安全性。当 leader 副本发生故障时会从 follower 中选举出一个 leader,但是 follower 中如果有和 leader 同步程度达不到要求的参加不了 leader 的竞选。
Kafka 的多分区(Partition)以及多副本(Replica)机制有什么好处呢?
- Kafka 通过给特定 Topic 指定多个 Partition, 而各个 Partition 可以分布在不同的 Broker 上, 这样便能提供比较好的并发能力(负载均衡)。
- Partition 可以指定对应的 Replica 数, 这也极大地提高了消息存储的安全性, 提高了容灾能力,不过也相应的增加了所需要的存储空间。
Kafka 架构
序号 | 组件 | 描述 |
---|---|---|
1 | 代理 | Kafka 集群通常由多个代理组成,以保持负载平衡。Kafka 代理是无状态的,因此它们使用 ZooKeeper 来维护其集群状态。一个 Kafka 代理实例每秒可以处理数十万次读写,每个代理可以处理 TB 级消息而不会影响性能。Kafka 代理领导者选举可以通过 ZooKeeper 完成。 |
2 | ZooKeeper | ZooKeeper 用于管理和协调 Kafka 代理。ZooKeeper 服务主要用于通知生产者和消费者有关 Kafka 系统中任何新代理的存在或 Kafka 系统中代理的故障。根据 Zookeeper 收到的有关代理存在或故障的通知,生产者和消费者做出决定并开始与其他代理协调他们的任务。 |
3 | 生产者 | 生产者将数据推送到代理。当新代理启动时,所有生产者都会搜索它并自动向该新代理发送消息。Kafka 生产者不会等待代理的确认,而是以代理可以处理的速度发送消息。 |
4 | 消费者 | 由于 Kafka 代理是无状态的,这意味着消费者必须使用分区偏移量来维护已消费的消息数量。如果消费者确认了特定的消息偏移量,则意味着消费者已经消费了所有先前的消息。消费者向代理发出异步拉取请求,以便准备好可供消费的字节缓冲区。消费者只需提供偏移量值即可倒回或跳转到分区中的任何点。消费者偏移量值由 ZooKeeper 通知。 |
Kafka 消息模型
早期的消息模型有两种:队列模型、发布-订阅模型。
使用队列(Queue)作为消息通信载体,满足生产者与消费者模式,一条消息只能被一个消费者使用,未被消费的消息在队列中保留直到被消费或超时。
列模型存在的问题:假如我们存在这样一种情况:我们需要将生产者产生的消息分发给多个消费者,并且每个消费者都能接收到完成的消息内容。这种情况,队列模型就不好解决了。
发布-订阅模型主要是为了解决队列模型存在的问题。
发布订阅模型(Pub-Sub) 使用主题(Topic) 作为消息通信载体,类似于广播模式;发布者发布一条消息,该消息通过主题传递给所有的订阅者,在一条消息广播之后才订阅的用户则是收不到该条消息的。
在发布 - 订阅模型中,如果只有一个订阅者,那它和队列模型就基本是一样的了。所以说,发布 - 订阅模型在功能层面上是可以兼容队列模型的。
Kafka 采用的就是发布 - 订阅模型。
RocketMQ 的消息模型和 Kafka 基本是完全一样的。唯一的区别是 Kafka 中没有队列这个概念,与之对应的是 Partition(分区)。
Zookeeper 作用
这部分内容参考和借鉴了这篇文章:https://www.jianshu.com/p/a036405f989c 。
ZooKeeper 主要为 Kafka 提供元数据的管理的功能:
- Broker 注册 :在 Zookeeper 上会有一个专门用来进行 Broker 服务器列表记录的节点。每个 Broker 在启动时,都会到 Zookeeper 上进行注册,即到/brokers/ids 下创建属于自己的节点。每个 Broker 就会将自己的 IP 地址和端口等信息记录到该节点中去
- Topic 注册 : 在 Kafka 中,同一个Topic 的消息会被分成多个分区并将其分布在多个 Broker 上,这些分区信息及与 Broker 的对应关系也都是由 Zookeeper 在维护。比如我创建了一个名字为 my-topic 的主题并且它有两个分区,对应到 zookeeper 中会创建这些文件夹:
/brokers/topics/my-topic/Partitions/0
、/brokers/topics/my-topic/Partitions/1
- 负载均衡 :上面也说过了 Kafka 通过给特定 Topic 指定多个 Partition, 而各个 Partition 可以分布在不同的 Broker 上, 这样便能提供比较好的并发能力。 对于同一个 Topic 的不同 Partition,Kafka 会尽力将这些 Partition 分布到不同的 Broker 服务器上。当生产者产生消息后也会尽量投递到不同 Broker 的 Partition 里面。当 Consumer 消费的时候,Zookeeper 可以根据当前的 Partition 数量以及 Consumer 数量来实现动态负载均衡。