Kafka 系统架构
Kafka 由 Producer、Broker、ZooKeeper、Consumer 四个模块组成。其中,ZooKeeper 用来存储元数据信息,集群中所有元数据都持久化存储在 ZooKeeper 当中。
协议和网络模块
Kafka 是自定义的私有协议,经过多年发展目前有 V0、V1、V2 三个版本,稳定在 V2 版本。
Kafka 协议从结构上来看包含协议头和协议体两部分,协议头包含基础通用的信息,协议体由于每个接口的功能参数不一样,内容结构上差异很大。
Kafka 服务端的网络层是基于 Java NIO 和 Reactor 来开发的,通过多级的线程调度来提高性能。
数据存储
Kafka 同样分为元数据存储和消息数据存储两部分。
元数据存储
Kafka 的元数据是存储在 ZooKeeper 里面的。ZooKeeper 会持久化存储全量元数据信息,Broker 本身不存储任何集群相关的元数据信息。
Kakfa 集群中的一些如消费进度信息、事务信息,分层存储元数据,以及 3.0 后的 Raft 架构相关的元数据信息,都是基于内置 Topic 来完成存储的。把数据存储在内置 Topic 中,算是一个比较巧妙的思路了,也是一个值得借鉴的技巧。
消息数据
当 Broker 收到数据后,是直接将数据写入到不同的分区文件中的。所以在消费的时候,消费者也是直接从每个分区读取数据。
Kafka 的存储结构是以 Topic 和分区维度来组织的。一个分区一个目录,目录名称是 TopicName + 分区号。
每个分区的目录下,都会有 .index、.log、.timeindex 三类文件。其中,.log 是消息数据的存储文件,.index 是偏移量(offset)索引文件,.timeindex 是时间戳索引文件。
分段是在.log 进行的,文件分段的默认数据大小也是 1G,可以通过配置项来修改。
Kafka 提供了根据过期时间和数据大小清理的机制,清理机制是在 Topic 维度生效的。当数据超过配置的过期时间或者超过大小的限制之后,就会进行清理。清理的机制也是延时清理的机制,它是根据每个段文件进行清理的,即整个文件的数据都过期后,才会清理数据。
生产者和消费者
在新版本的 Kafka 中,客户端是通过直连 Broker 完成寻址操作的,不会跟 ZooKeeper 交互。即 Broker 跟 ZooKeeper 交互,在本地缓存全量的元数据信息,然后客户端通过连接 Broker 拿到元数据信息,从而避免对 ZooKeeper 造成太大负载。
生产者
Kafka 协议提供了批量(Batch)发送的语义。所以生产端会在本地先缓存数据,根据不同的分区聚合数据后,再根据一定的策略批量将数据写入到 Broker。因为这个 Batch 机制的存在,客户端和服务端的吞吐性能会提高很多。
消费者
Kafka 的消费端只提供了 Pull(拉)模式的消费。
当客户端成功消费数据后,会往服务端提交消费进度信息,此时服务端也不会删除具体的消息数据,只会保存消费位点信息。位点数据保存在内部的一个 Topic(__consumer_offset)中。消费端同样提供了自动提交和手动提交两种模式。当消费者重新启动时,会根据上一次保存的位点去消费数据,用来避免重复消费。
HTTP 协议支持和管控操作
Kafka 内核是不支持 HTTP 协议的,如果需要支持,则需要在 Broker 前面挂一层代理。如 Confluent 开源的 Kafka Rest。
Kafka 命令行提供了管控、生产、消费、压测等功能,其底层就是通过客户端 SDK 和 Broker 进行交互的。我们在代码里面也可以通过客户端 SDK 完成相应的操作,不用必须通过命令行。
此文章为11月Day12学习笔记,内容来源于极客时间《深入拆解消息队列 47 讲》