1、外部数据是怎样的接入到kafka的?
外部数据接入到kafka的流程示意图:
(1)接入数据流程
(1)producer先从broker-list的节点中找到该partition的leader;
(2)然后producer将消息发送给作为leader的partition;
(3)leader收到消息后,将消息写入本地log;
(4)followers从leader中pull消息,实现replication的副本备份机制,同样写入本地log;
(5)replication写入本地log后向leader发送ack(确认);
(6)leader收到所有的replication的ack之后,向producer发送ack;
(7)producer收到leader的ack,证明生产的数据已被kafka成功写入。
(2)kafka的ack应答机制(request.requred.acks中修改ack值)
ack = 0:producer不等待broker中leader的ack;broker接收消息后如果还没写入本地log,broker就发生故障,可能会丢失数据;
ack = 1:producer等待leader的ack,但是不等待replication的ack;这样partition的leader消息落盘成功后返回ack,但是在follwer备份成功之前若leader发生故障,也会丢失数据;延迟时间短但是可靠性低;
ack = -1:producer等待leader和replication的ack,这样只有等leader中partition消息落盘成功,并且follower中replication消息备份落盘成功,才会给producer返回ack,数据一般不会丢失,延迟时间长但是可靠性高。
2、kafka的数据存储
(1)kafka的重要概念
-
Broker:消息中间件处理结点,一个Kafka节点就是一个broker,多个broker可以组成一个Kafka集群;
-
Topic:一类消息,例如page
-
view日志、click日志等都可以以topic的形式存在,Kafka集群能够同时负责多个topic的分发;
-
Partition:topic物理上的分组,一个topic可以分为多个partition,每个partition是一个有序的队;
-
Segment:每个partition又由多个segment file组成;
-
offset:每个partition都由一系列有序的、不可变的消息组成,这些消息被连续的追加到partition中。partition中的每个消息都有一个连续的序列号叫做offset,用于partition唯一标识一条消息;
-
message:这个算是kafka文件中最小的存储单位,即是 a commit log。
kafka的message是以topic为基本单位,不同topic之间是相互独立的。每个topic又可分为几个不同的partition,每个partition存储一部的分message。topic与partition的关系如下:
其中,partition是以文件夹的形式存储在具体Broker本机上。
(2)partition中的数据文件
(2-1) segment中的文件
对于一个partition(在Broker中以文件夹的形式存在),里面又有很多大小相等的segment数据文件(这个文件的具体大小可以在config/server.properties中进行设置),这种特性可以方便old segment file的快速删除。
下面先介绍一下partition中的segment file的组成:
segment file 组成:由2部分组成,分别为index file和data file,这两个文件是一一对应的,后缀”.index”和”.log”分别表示索引文件和数据文件;
segment file 命名规则:partition的第一个segment从0开始,后续每个segment文件名为上一个segment文件最后一条消息的offset,ofsset的数值最大为64位(long类型),20位数字字符长度,没有数字用0填充。如下图所示:
关于segment file中index与data file对应关系图,这里我们选用网上的一个图片,如下所示:
segment的索引文件中存储着大量的元数据,数据文件中存储着大量消息,索引文件中的元数据指向对应数据文件中的message的物理偏移地址。以索引文件中的3,497为例,在数据文件中表示第3个message(在全局partition表示第368772个message),以及该消息的物理偏移地址为497。
注:Partition中的每条message由offset来表示它在这个partition中的偏移量,这个offset并不是该Message在partition中实际存储位置,而是逻辑上的一个值(如上面的3),但它却唯一确定了partition中的一条Message(可以认为offset是partition中Message的id)。
(2-2) message文件
message中的物理结构为:
(2-3) 数据文件的内部实现方法
Partition数据文件包含了若干上述格式的message,按照offset由小到大排列在一起,它实现的类是FileMessageSet,类图如下:
它的主要方法如下:
- append: 把给定的ByteBufferMessageSet中的Message写入到这个数据文件中。
- searchFor: 从指定的startingPosition开始搜索,找到第一个Message判断其offset是大于或者等于指定的offset,并返回其在文件中的位置 - - Position。它的实现方式是从startingPosition开始读取12个字节,分别是当前MessageSet的offset和size。如果当前offset小于指定的offset,那么将position向后移动LogOverHead+MessageSize(其中 - LogOverHead为offset+messagesize,为12个字节)。
- read:准确名字应该是slice,它截取其中一部分返回一个新的FileMessageSet。它不保证截取的位置数据的完整性。
- sizeInBytes: 表示这个FileMessageSet占有了多少字节的空间。
- truncateTo: 把这个文件截断,这个方法不保证截断位置的Message的完整性。
- readInto: 从指定的相对位置开始把文件的内容读取到对应的ByteBuffer中。
3、参考资料
Kafka的数据生产——数据写入流程 & 提高kafka的消费速率:
https://blog.csdn.net/wx1528159409/article/details/88663974
kafka接入学习:https://blog.csdn.net/u014001866/article/details/50971098