Kafka 基础架构、工作流程、存储机制介绍

一、kafka基础架构

在这里插入图片描述

  • Producer :消息生产者,向 kafka broker 发消息的客户端;
  • Consumer :消息消费者,向 kafka broker 取消息的客户端;
  • Consumer Group :消费者组,由多个 consumer 组成。消费者组内每个消费者负责消费不同分区的数据,一个分区只能由一个组内消费者消费;消费者组之间互不影响。所有的消费者都属于某个消费者组,即消费者组是逻辑上的一个订阅者
  • Broker :一台 kafka 服务器就是一个 broker。一个集群由多个 broker 组成。一个 broker 可以容纳多个 topic。
  • Topic :可以理解为一个队列,生产者和消费者面向的都是一个 topic;
  • Partition:为了实现扩展性,一个非常大的 topic 可以分布到多个 broker(即服务器)上, 一个 topic 可以分为多个partition,每个 partition 是一个有序的队列;
  • Replica:副本,为保证集群中的某个节点发生故障时,该节点上的 partition 数据不丢失, 且 kafka 仍然能够继续工作,kafka 提供了副本机制,一个 topic 的每个分区都有若干个副本, 一个 leader 和若干个 follower。
  • leader:每个分区多个副本的“主”,生产者发送数据的对象,以及消费者消费数据的对象都是 leader。
  • follower:每个分区多个副本中的“从”,实时从 leader 中同步数据,保持和 leader 数据 的同步。leader发生故障时,某个 follower 会成为新的 follower。

二、Kafka 工作流程及文件存储机制

1、kafka工作流程
在这里插入图片描述

Kafka 中消息是以 topic 进行分类的,生产者生产消息,消费者消费消息,都是面向 topic
的。topic 是逻辑上的概念,而 partition 是物理上的概念,每个 partition 对应于一个 log 文
件,该 log 文件中存储的就是 producer 生产的数据。Producer 生产的数据会被不断追加到该log 文件末端,且每条数据都有自己的 offset。消费者组中的每个消费者,都会实时记录自己消费到了哪个 offset,以便出错恢复时,从上次的位置继续消费。

2、kafka文件存储机制

在这里插入图片描述
2.1、存储机制

  • 由于生产者生产的消息会不断追加到 log 文件末尾,为防止 log 文件过大导致数据定位 效率低下,Kafka采取了分片和索引机制,将每个 partition 分为多个 segment(逻辑概念,等于index+log文件)。
  • 每个partition(目录)相当于一个巨型文件被平均分配到多个大小相等的segment(片段)数据文件中(每个segment文件中消息数量不一定相等),这种特性也方便old segment的删除,即方便已被消费的消息的清理,提高磁盘的利用率每个partition只需要支持顺序读写就行,segment的文件生命周期由服务端配置参数(log.segment.bytes,log.roll.{ms,hours}等若干参数)决定。
  • 每个segment对应两个文件——“.index”文件和“.log”文件。分别表示为segment索引文件数据文件(引入索引文件的目的就是便于利用二分查找快速定位message位置)。这些文件位于一个文件夹下,该文件夹的命名规则为:topic名称+分区序号(partition全局的第一个segment从0开始,后续每个segment文件名以当前segment的第一条消息的offset命名,数值大小为64位,20位数字字符长度,没有数字用0填充。)。例如,first
    这个 topic 有三个分区,则其对应的文件夹为 first-0,first-1,first-2。
00000000000000000000.index
00000000000000000000.log
00000000000000170410.index
00000000000000170410.log
00000000000000239430.index
00000000000000239430.log
[root@centos7-1 data]# pwd
/data/kafka/data
#这个需要安装插件 yum -y install tree
[root@centos7-1 data]# tree
.
├── cleaner-offset-checkpoint
├── meta.properties
├── recovery-point-offset-checkpoint
├── replication-offset-checkpoint
# partition目录(topic名称+分区序号)
├── test-0
# segment索引文件
│   ├── 00000000000000000000.index
# 数据文件
│   ├── 00000000000000000000.log
# 0.8版本之前的kafka没有timeindex文件,这是kafka的具体时间日志
│   └── 00000000000000000000.timeindex
│   ├── 00000000000000170410.index
│   ├── 00000000000000170410.log
│   └── 00000000000000170410.timeindex
├── test-1
│   ├── 00000000000000000000.index
│   ├── 00000000000000000000.log
│   └── 00000000000000000000.timeindex
└── test-2
    ├── 00000000000000000000.index
    ├── 00000000000000000000.log
    └── 00000000000000000000.timeindex

index 和 log 文件以当前 segment 的第一条消息的 offset 命名。下图为 index 文件和 log
文件的结构示意图。
在这里插入图片描述
2.2、index和log文件详解

.index索引文件存储大量的索引信息,.log数据文件存储大量消息数据(Message),索引文件中的元数据指向对应数据文件中Message的物理偏移地址。以index索引文件中的元数据3,497为例,依次在数据文件中表示第三个Message(在全局Partition中表示第368772个message),以及该消息的物理偏移地址为497。索引和日志文件内部的关系如下图:

在这里插入图片描述

2.3、message的结构

在这里插入图片描述

  • CRC32:4个字节,消息的校验码。
  • magic:1字节,魔数标识,与消息格式有关,取值为0或1。当magic为0时,消息的offset使用绝对offset且消息格式中没有timestamp部分;当magic为1时,消息的offset使用相对offset且消息格式中存在timestamp部分。所以,magic值不同,消息的长度是不同的。
  • attributes: 1字节,消息的属性。其中第0~
    2位的组合表示消息使用的压缩类型,0表示无压缩,1表示gzip压缩,2表示snappy压缩,3表示lz4压缩。第3位表示时间戳类型,0表示创建时间,1表示追加时间。
  • timestamp: 时间戳,其含义由attributes的第3位确定。
  • key length:消息key的长度。
  • key:消息的key。
  • value length:消息的value长度。
  • value:消息的内容

2.4、如何通过offset查找Message

  1. 二分查找获取对应index索引文件,获取到对应的物理offset

  2. 拿着物理offset去log数据文件顺序查找对应消息

  3. 返回查找到的消息

例如,读取offset=368776的Message,需要通过如下两个步骤。

  • 第一步:查找Segment File.
    00000000000000000000.index表示最开始的文件,起始偏移量(offset)为0;第二个文件00000000000000368770.index的起始偏移量为368770,依次类推。以起始偏移量命名并排序这些文件,只要根据offset二分查找文件列表,就可以快速定位到具体文件。

当offset=368776时,定位到00000000000000368770.index|log。

  • 第二步:通过Segment File 查找Message。
    通过第一步定位到Segment File,当offset=368776时,依次定位到00000000000000368770.index的元数据物理位置和00000000000000368770.log的物理偏移地址,然后再通过00000000000000368770.log顺序查找,直到offset=368776为止。
    Segment Index File采取稀疏索引存储方式,可以减少索引文件大小,通过Linux mmap接口可以直接进行内存操作。稀疏索引为数据文件的每个对应Message设置一个元数据指针,它比稠密索引节省了更多的存储空间,但查找起来需要消耗更多的时间。

猜你喜欢

转载自blog.csdn.net/weixin_46122692/article/details/109249902