kafka基本知识

基本概念

  1. 消息以主题(Topic)来分类,每一个主题都对应一个「消息队列」

  2. 面相消费者和生产者,物理上存储的其实是 Partition,每一个 Partition 最终对应一个目录,里面存储所有的消息和索引文件。

    默认情况下,每一个 Topic 在创建时如果不指定 Partition 数量时只会创建 1 个 Partition。比如,我创建了一个 Topic 名字为 test ,没有指定 Partition 的数量,那么会默认创建一个 test-0 的文件夹,这里的命名规则是:<topic_name>-<partition_id>

  3. 任何发布到 Partition 的消息都会被追加到 Partition 数据文件的尾部,这样的顺序写磁盘操作让 Kafka 的效率非常高

具体结构

每个 Partition 都为一个目录,而每一个目录又被平均分配成多个大小相等的 Segment File 中,Segment File 又由 index file 和 data file 组成,他们总是成对出现,后缀 “.index” 和 “.log” 分表表示 Segment 索引文件和数据文件。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
#两个topic:topic0和topic1
| --topic1-0
| --00000000000000000000.index
| --00000000000000000000.log
| --00000000000000368769.index
| --00000000000000368769.log
| --00000000000000737337.index
| --00000000000000737337.log
| --00000000000001105814.index
| --00000000000001105814.log


| --topic2-0
| --topic2-1

Segment 是 Kafka 文件存储的最小单位。Segment 文件命名规则:Partition 全局的第一个 Segment 从 0 开始,后续每个 Segment 文件名为上一个 Segment 文件最后一条消息的 offset 值。

Kafka 是如何准确的知道 message 的偏移的呢?这是因为在 Kafka 定义了标准的数据存储结构,在 Partition 中的每一条 message 都包含了以下三个属性:

  • offset:表示 message 在当前 Partition 中的偏移量,是一个逻辑上的值,唯一确定了 Partition 中的一条 message,可以简单的认为是一个 id;
  • MessageSize:表示 message 内容 data 的大小;
  • data:message 的具体内容

消费组

消费组

  1. 消费组的概念:在Kafka中,消费组是一组消费者的集合,这些消费者共同订阅一个或多个主题,共享消息的消费。Kafka保证一个分区内的消息只被消费组中的一个消费者处理,这样可以在消费者间实现负载均衡。
  2. 分区与消费者的关系:每个消费者负责读取指定主题的一个或多个分区中的消息。如果消费者的数量等于分区的数量,那么每个消费者负责读取一个分区的消息。如果消费者数量少于分区数量,某些消费者将负责多个分区。如果消费者数量多于分区数量,将会有一些空闲的消费者。

支持多应用消费

  • 全量消息读取:Kafka允许多个消费组独立地订阅同一个主题。这意味着每个消费组都可以从头到尾读取主题中的所有消息,而不会影响到其他消费组。这个特性对于需要处理相同数据集的不同应用非常重要。
  • 消费组与应用的关系:通常,每个独立的应用会有自己的消费组。这样,即使多个应用需要读取并处理同一主题的消息,它们也能保证获取到全量的消息数据。每个消费组的消费进度是独立管理的。

消费顺序

Kafka 中一个 topic 中的消息是被打散分配在多个 Partition(分区) 中存储的, Consumer Group 在消费时需要从不同的 Partition 获取消息,那最终如何重建出 Topic 中消息的顺序呢?

答案是:没有办法。Kafka 只会保证在 Partition 内消息是有序的,而不管全局的情况。

可以指定消息的key,确保相同的key发布到同一个分区

可靠性

  • 对于一个分区来说,它的消息是有序的。如果一个生产者向一个分区先写入消息A,然后写入消息B,那么消费者会先读取消息A再读取消息B。
  • 当消息写入所有in-sync状态的副本后,消息才会认为已提交(committed)。这里的写入有可能只是写入到文件系统的缓存,不一定刷新到磁盘。生产者可以等待不同时机的确认,比如等待分区主副本写入即返回,后者等待所有in-sync状态副本写入才返回。
  • 一旦消息已提交,那么只要有一个副本存活,数据不会丢失。
  • 消费者只能读取到已提交的消息

主题的分区数目

当你创建一个Kafka主题时,可以指定分区的数量。分区数量不是随机的,而是由你在创建主题时设置的。分区使得Kafka可以在多个服务器上分布数据和负载,提高吞吐量。

1
kafka-topics.sh --create --bootstrap-server <broker> --replication-factor 1 --partitions 3 --topic <topic_name>

Kafka配置文件修改与参数

Kafka的配置主要在其配置文件中设置,例如server.properties。有许多配置参数,比如:

  • broker.id:唯一标识每个Kafka节点。
  • log.dirs:存储日志文件的位置。
  • zookeeper.connect:Zookeeper的连接信息,Kafka用它来存储集群的状态。

更改配置文件通常是直接编辑文件,然后重启Kafka服务。

消费者读取启动之前的数据

消费者可以读取到启动之前的数据。这取决于消费者的auto.offset.reset配置:

  • 设置为earliest时,消费者将从有效负载的最开始读取数据。
  • 设置为latest时,消费者将从新产生的数据开始读取。

使用Go语言的Sarama库,这可以在消费者配置中设置:

1
2
config := sarama.NewConfig()
config.Consumer.Offsets.Initial = sarama.OffsetOldest

事务的默认隔离级别

默认为读未提交

Kafka的事务隔离级别通过isolation.level配置控制,有两个值:

  • read_uncommitted(默认):消费者可以读取到未提交的消息。
  • read_committed:消费者只能读取到已提交的消息。

在Go语言中,使用Sarama库设置消费者的隔离级别时,需要使用Kafka版本0.11.0或更高,并配置消费者如下:

1
2
3
config := sarama.NewConfig()
config.Version = sarama.V0_11_0_0 // 必须设置版本支持事务
config.Consumer.IsolationLevel = sarama.ReadCommitted // 设置为读已提交

kafka序列化


kafka基本知识
http://example.com/2024/03/19/kafka/基本知识/
作者
Mrxiad
发布于
2024年3月19日
许可协议