美文网首页
七 消息是怎样存储在Kafka集群上的

七 消息是怎样存储在Kafka集群上的

作者: overflowedstack | 来源:发表于2021-06-07 10:28 被阅读0次

Kafka文档

1. Kafka集群用log和index文件来存储消息

例如00000.log里存放的就是从offset 0开始的消息,相应地,00000.index里存放的是特定offset的消息在00000.log文件中的地址。

而当00000.log文件大小达到某个特定值时,就会写入下一个文件,00078.log以及00078.index。里面存放的是最小位移为78的消息。

另外,索引采用的是稀疏索引,并没有对每一个offset都建立索引。

$ ls -l
total 40
-rw-r--r--  1 user  admin         0  3 27 15:09 00000000000000000000.index
-rw-r--r--  1 user  admin       224  3 27 15:09 00000000000000000000.log
-rw-r--r--  1 user  admin        12  3 27 15:09 00000000000000000000.timeindex
-rw-r--r--  1 user  admin  10485760  4  3 15:19 00000000000000000078.index
-rw-r--r--  1 user  admin       107  4  3 15:19 00000000000000000078.log
-rw-r--r--  1 user  admin        10  4  3 15:19 00000000000000000078.snapshot
-rw-r--r--  1 user  admin  10485756  4  3 15:19 00000000000000000078.timeindex

log文件大小是由kafka segment参数决定的。默认是1个G.

# The maximum size of a log segment file. When this size is reached a new log segment will be created.
log.segment.bytes=1073741824

2. Kafka写文件的方式(Kafka吞吐量大的部分原因)

2.1 页缓存

操作系统中,有机制将磁盘中的数据放入内存中,也就是页缓存。进程对页缓存读写,操作系统负责页缓存和磁盘之间的数据同步。

Kafka中大量使用了页缓存,大大提高了系统的吞吐量。

2.2 顺序写

Kafka写文件采用了追加的方式,顺序写入磁盘的。
磁盘内部写入的时候,分为随机写入,和顺序写入。随机写入需要磁盘的磁头不断变道,寻址,再进行写操作。变道寻址会占用不少时间。而顺序写入,基本上不用变道和寻址,省去了很多时间。
所以Kafka写磁盘效率很高。

2.3 零拷贝 (zero-copy)

另外,还采用了零拷贝技术。零拷贝指的是减少数据拷贝的次数。
主要体现在 接收生产者发送的数据,和 取出消息发送给消费者时。

  • 传统方式中,接收消息,存入磁盘,会发生几次数据拷贝:
    首先,从网盘拷贝到socket;
    再从内核态的socket拷贝到用户态的应用内存;
    接着从用户态的内存拷贝到内核态的read buffer;
    最后从read buffer拷贝到硬盘。

这个过程发生了4次数据拷贝,2次用户态和内核态之间的切换,都是开销很大的。


传统方式
  • 在kafka中,通过零拷贝,也就是直接在内核态,将数据直接从网卡传输到磁盘,不经过应用程序,也不用切换到用户态。大大提高了性能。

注:操作系统有一些核心的功能,涉及到底层的很多关键操作,是不能随便让哪个程序就能去做的。那么需要做这部分操作,就需要到内核态执行。
一般情况下,应用程序都是在用户态执行,它只需要一些普通的权限就可以了。当应用程序需要执行一些底层的操作时,就需要先切换到内核态,才有权限去做。
而切换时,需要通过很多操作来完成,例如堆栈的切换等,开销是比较大的。(用户态与内核态

3. Kafka的日志和index是什么时候写入的

Kafka的日志并不是实时写入磁盘的。消息先被写入页缓存,待操作系统统一进行刷盘,将页缓存写入磁盘。
另外,kafka也提供了强制间隔刷盘,以及同步刷盘的选项,可以通过参数来指定。但是同步刷盘并不推荐,因为它严重影响了性能。

那么间隔刷盘,消息会不会丢呢?kafka的多副本机制是可靠性的保证,那么单个replication如果突发断电等,数据丢失,有其他副本依然保存了数据。所以间隔刷盘,消息可靠性依然是有保证的。

4. 读取某个offset的消息

在kafka中,topic的某个partition的每个log文件作为log segment,是通过跳表来存储的。
当需要读取某个offset的消息时,先通过跳表来找到相应的log segment。通过index文件找到相应offset的地址,再去log segment中找到相应地址的消息。

5. Kafka集群中的log是怎样被清理的

log清理有两种机制,第一种是日志删除,一种是日志压缩。

5.1 日志删除

按一定的保留策略,直接删除某些log segment。

  • 时间
    segment所存储消息的时间大于特定值,则需要被删除。
  • 大小
    log segment的总大小大于特定值,则删除前面的segment。
  • offset
    若segment的下一个segment 偏移量小于起始偏移量,则删除此segment。

kafka有一个专门负责删除日志的任务,会周期性地扫描segment。符合删除条件的话,就将其标为 .deleted后缀,最后通过一个延迟任务统一删除。这个延迟时间可以通过参数来指定。

5.2 日志压缩

对于相同key的消息,只保留其最新消息。

**********

理解了kafka的消息存储,就了解kafka为什么吞吐量大了

  1. 消息格式本身经过了合理的设计,用到一些机制,例如存相对offset的方式,来减小消息长度。
  2. 虽然用磁盘存储,但是用到了页缓存、顺序写磁盘、零拷贝的技术,大大提高了读写速度。
  3. 有数据文件,和相应的索引文件,读取消息的效率也非常之高。

相关文章

网友评论

      本文标题:七 消息是怎样存储在Kafka集群上的

      本文链接:https://www.haomeiwen.com/subject/ujfdcltx.html