Kafka -- 消息发送存储流程

kafka的目录结构和RocketMQ -- 消息发送存储流程是不一样的,但是某部分思想还是一致的。
首先是kafka-logs下,放的是topic+partition的文件夹,比如topic为test的有2个partition(假设都在这个Broker上),那就有两个文件,分别为test-0,test-1。
每个文件下,都有很多log文件以及对应的两个索引文件。每个log文件又叫segment。
segment文件的大小也是1G,每个文件名是消息的物理偏移量。
Kafka -- 消息发送存储流程
文章图片

当broker接收到消息的时候,首先会进行一些判断,比如权限验证、acks的参数是否合法。
等验证通过后,遍历消息里的每个分区处理数据。比如test对应的分区0,根据上面的目录结构图,就知道会找到test-0的副本里。
【Kafka -- 消息发送存储流程】找到后,就会申请读锁,并获取leader的partition,因为只有leader才可以写数据。
Kafka -- 消息发送存储流程
文章图片

上面加的是读锁,等写入segment文件的时候,还要再加一次锁。
Kafka -- 消息发送存储流程
文章图片

申请到锁后,开始选择segment文件,如果是刚开始写入日志文件的时候,此时并没有segment文件,所以就会创建一个大小为1G名字为00000000000000000000的日志文件。如果已经存在多个日志文件,那直接取最后一个日志文件,因为日志文件写完才会创建一个新的日志文件,那最后一个日志文件就是当前需要写入的。
如果这个写入的消息大小和当前选择的segment文件大小加起来超过1G,那又会创建一个新的segment文件。
如果segment对应的index或者timeIndex满了,那也会创建一个新的segment文件。
Kafka -- 消息发送存储流程
文章图片

获取到segment文件后,就把消息写入内存中。
Kafka -- 消息发送存储流程
文章图片

每写4096字节的消息,就开始写两个索引文件,当然写入的时候,还是要先加锁。
所以我们的索引文件,并不是连续的。
Kafka -- 消息发送存储流程
文章图片

写完内存后,就会判断是否需要刷盘,默认是不刷盘的,把刷盘操作交给操作系统定期的执行,所以会有数据丢失的情况。

    推荐阅读