Kafka 构成
- Zookeeper: 管理kafka的原数据
- 控制器(broker):集群部署的情况下,每台集群就是一个Broker,多个Broker会选举一个Controler(谁先注册,谁就是Controller)
- 主题(Topic)是逻辑上的概念, 它有⼀个或多个分区(Partition), 消息就是存在这些具体的分区⾥⾯。
- 分区(Partition)其实也是⼀个逻辑上的概念, 每个主题会有⼀个/多个分区, 我们⽣产的消息会追加到这些分区的Log⽂件⾥⾯, 同⼀个主题下的分区包含的消息是不同的。消息是以追加的形式存储在分区中。消息在被追加到分区⽇志⽂件的时候都会分配⼀个特定的偏移量(offset),offset是消息在分区中的唯⼀标识。Kafka保证分区有序,并不保证主题消息有序。
- 副本(Replica)是分区的物理实现, ⼀个分区可以有多个副本, ⼀个分区的多个副本分为Leader副本、Follower副本, Leader副本负责提供读写能
- ⼒,Follower副本会从Leader副本同步数据⽤于备份。
- 生产者(customer):⽣产者负责创建消息, 然后将其投递到Kafka中, 当然这些消息最终也是落到具体的某些Broker中存储(之所以说“某些”,是因为消息是可以有多副本存储的)
- 消费者(Consumer):消费者负责接受消息, 它会连接到Kafka上并且监听是否有新的消息是否需要被消费
Kafka是一个集群部署的模式,一个集群多台集群每个机器就是一个Brokers,创建不同的topic,topic下可以创不同的分区partition,每个partition会有多个副本,不同的副本落在不同的Brokers,保障了高可用;
Kafka 文件存储设计
Kafka 是直接通过写磁盘的方式来,在设计时采用了文件追加的方式来写入消息, 即只能在日志文件的尾部追加新的消息,并且也不允许修改写入的消息, 这种方式属于典型的顺序写盘的操作,所以就算 kafka 使用磁盘作为存储介质,它所能承载的吞吐量也不容小觑。
Kafka为什么这么快
- 利用partition 实现并行处理
一个topic包含一个或多个partition,不同的partition可位于不同的节点,每个partition对应一个文件夹,即使同一个节点页可以控制到不同的磁盘,充分利用了分布式集群的优势
- 顺序写磁盘
Kafka 中每个分区是一个有序的,不可变的消息序列,新的消息不断追加到 partition 的末尾,这个就是顺序写(Partition 分为多个 Segment,每个 Segment 对应一个物理文件,通过删除整个文件的方式去删除 Partition 内的数据)
- 零拷贝技术、页缓存
零拷贝:抛开原有数据IO复制,减少IO的切换
页缓存:读数据读缓存,写数据写缓存积攒一定数据量后再进行写,减少IO读写
(刷盘参数:
log.flush.interval.messages 在将消息刷新到磁盘之前,在日志分区上累积的消息数量
log.flush.interval.ms 在刷新到磁盘之前,任何topic中的消息保留在内存中的最长时间(以毫秒为单位) )
- 批处理
Kafka 的客户端和 broker 还会在通过网络发送数据之前,在一个批处理中累积多条记录 (包括读和写)。记录的批处理分摊了网络往返的开销,使用了更大的数据包从而提高了带宽利用率。
具体实现如下:
每一个partition都有一个队列,达到一定数量就发送,总共队列由内存空间由buffer.memory配置,32MB。
数据压缩协议
Kafka 支持 GZIP、Snappy、LZ4 和 ZStandard 压缩协议。
分区越多,吞吐量不一定越大
在一定条件下,分区数的数量是和吞吐量成正比的,分区数和性能也是成正比的。但是超过了限度后,不升反降,文件的句柄开销大
每个 partition 都会对应磁盘文件系统的一个目录。在 Kafka 的数据日志文件目录中,每个日志数据段都会分配两个文件,一个索引文件和一个数据文件。每个 broker 会为每个日志段文件打开一个index 文件句柄和一个数据文件句柄。因此,随着 partition 的增多,所需要保持打开状态的文件句柄数也就越多,最终可能超过底层操作系统配置的文件句柄数量限制。