Kafka原理总结
Kafka
- 高吞吐
Kafka常用于大数据场景,因为它对批量传输的场景做了优化,producer发出的数据需要成批一次性发给Consumer。 - 分布式
Broker多个副本保存多个partition,partition也有多个副本。 - Pub/Sub
意味着和大部分MQ中间件一样会有Producer、Consumer、Broker这几个组件。 - Scala
和Java有关系,编译器不同但是一般都使用hotspot虚拟机运行字节码。
概念
topic
消息类别partition
topic的分区,一个topic可以有多个分区。
每个partition有主备来实现高可用,offset
消息在日志中的位置,即partition中的偏移量,也是该消息的唯一序号。Broker
Kafka服务端,负责消息存储和转发Producer
消息生产者Consumer
消息消费者Consumer Group
消费者分组Zookeeper
保存集群中Broker、topic、Partition等的元数据。
还负责Broker的故障发现、partition leader选举
整体架构
数据存储
partition数据文件
partition存储数据,每条Message数据包含:offset、size、data这3个属性:
- offset
在partition文件中的偏移量,不过是逻辑上的偏移量而不是物理偏移量,因为每个topic都会包含多个partition,offset记录的是从第0个partition初始位置开始的偏移量。 - size
数据大小 - data
消息本身数据
partition高可用
partition有主从来实现高可用,每个topic的partition有N个副本,N
数据文件分段segment
partition物理上由多个segment文件组成,每个offset以该offset的初始偏移量命名,在查找某个offset的消息的时候,可以直接用二分查找来定位。
为什么要有segment?
分批存储,当segment中的数据都被消费后可以直接将文件删除(消息清理),如果只存partition的话文件只会越来越大。
数据文件索引
分段数据只能按offset查询数据,必须要建立索引,索引文件名和数据文件的名字是一样的,只是文件扩展名为.index。
index文件不是给每条数据建立索引,而是每隔一定字节(每隔6个offset)的数据建立一条索引,好处是占用的空间少,可以尽可能将索引文件保存到内存中;缺点是没法一次性定位到数据所处的位置,需要在小范围内做一次顺序扫描。
index文件中存储的数据格式为:<offset, position>
。
offset是消息的标识,position表示消息具体存储位置。
需要注意的是Kafka不支持按tag过滤,Kafka不适合用于一些复杂的业务场景,比如订单topic可能会分食品订单(tag=food)和服装订单(tag=cloth),有一个索引服务会订阅该订单topic建索引,后来来了个下游服务只对食品(food)感兴趣,就没法使用Kafka来实现了。
Kafka如果找到一条数据
- 先拿到offset
- 二分查找找segment
- 从segment找消息
将offset转换为物理偏移量。
Kafka读写速度为什么快?
- 顺序写
每个新消息写入到partition、segment的末尾 - 二分查找
通过二分查找找数据对应的segment文件,在文件中利用offset定位数据实际存储的位置。
消息发送
路由
如上所述,topic由多个partition组成,partition均分在不同broker上,多个partition通过Producer端的路由来均衡负载,提高整体吞吐量。
路由方式可以是:
- 随机
- hash
批量发送
批量发送是提高消息吞吐量的最重要方式。
Producer端在内存中合并多条消息后,以一次请求的方式发送这批数据。
优点是减少IO次数,提高吞吐量,缺点是减小了消息的实时性。