Kafka (2) - 消息存储以及零拷贝技术

  这小节我们仔细聊一下消息在kafka中是怎么存储的,以及非常关键的零拷贝技术在Kafka中的实现。

一、生产者产生的消息是怎么存储的

  上文中我们介绍了,消息从生产者发送到Kafka集群之后,会被分到一个Topic的不同分区中。然后Kafka在存储数据的时候是直接存储到磁盘上的,但是却不是整个Topic或者整个分区中的消息都存储在一个文件中,而是细化到每个分区,然后又细分多个Segment的。

  首先是细分到每个分区,对应目录的命名规则是<topic_name>_<partition_id>,之前说的是一个消息根据一定的条件被分到Topic的不同分区中,那么不同的分区是怎么对应到不同的broker上的呢?也是有一定的策略:

  • 将N个可用的broker和M个Topic的分区进行排序
  • 遍历分区,将第i个(属于M)分区 % N,得出分区被分配的broker

接下来第二个问题:分区的日志存储?

  因为每个分区存储的日志也非常多,所以kafka并没有采用将分区的日志写到同一个文件的方式,而是将日志分成多个LogSegment段,每个LogSegment对应一个index文件和一个log文件。其中索引文件是用来保存offset信息,日志文件用来保存消息主体。

 

 对应关系大概是这样,index文件中记录了offset和position信息,比如917就是offset,17800就是log文件的物理position信息。所以一条消息的查找过程大概就是这样的:

1.首先根据offset在分区的所有LogSegment中查找包含的index文件,因为索引文件是以上一个文件最后一个offset信息来命名的。

2.找到对应的index文件之后根据offset去查找对应的offset和position映射关系

3.根据position去对应的log文件中查找消息体

这里我们首先通过索引文件名来查找索引文件,在索引文件中查找offset记录都是在一个有序的集合中查找,所以是可以通过二分的方式来提高查询效率的,了解了这些之后我们就可以知道,当生产者将一条消息发送到broker之后,是以顺序的方式写到到对应的LogSegment中的,避免了随机写带来的性能消耗。

 

因为这样记录的日志信息会比较的多,而很多场景中其实我们只关注消息的最终状态就够了,所以基于这个场景Kafka提供了日志压缩的策略,开启了日志压缩功能Kafka后台会启动Cleaner线程池,定期的将相同的key进行合并,只保留最新的value。

二、消费者读取消息

  消息存储到磁盘上了,那么在消费者需要消费的时候,就需要从磁盘上读取出来,然后再通过网络发送给消费者,这里面就涉及到了很多文件拷贝的流程,我们通过一张图来了解一下。

 

 

   这里面的文字就不再赘述了,这里面流程优化就是运用了一个比较关键的概念:零拷贝。

通过看上面的流程可以知道,文件从磁盘需要拷贝多次,但是2和3的拷贝其实是没有产生任何价值的,因为在应用层没有做任何处理。所以这里说的零拷贝其实就是去掉这些无用的拷贝。

所以就对应如下的流程图了:

 

 

   但是到这还不算完,还有一个更厉害的武器:DMA  (Direct Memory Access),这里怎么理解呢。就是我们想要访问内存,需要通过CPU来完成中转。但是这个技术可以直接绕过CPU来操作主内存,这样就减少了CPU的性能消耗,提高了执行的效率。

  然后现在很多硬件都是支持DMA的,比如上面流程图中的网卡,那么回到这里我们再看,首先消息被从磁盘上读取到read buffer中,而在内核中Socker buffer和Read Buffer其实就是两种不同的文件描述符,因为都是在内核中操作,所以这里通过sendfile直接将read buffer中数据的位置和长度信息存储到socker buffer中,然后DMA直接读取read buffer中的数据,这就是Kafka基于零拷贝带来的性能提升。

三、日志的清理

  上面我们说到消息是被存储在每个LogSegment中的,那么消息多了磁盘空间也会不足。而且消息也不是永久保存的,所以这里就需要提一下两种日志的清理策略:

  • 根据消息的保留时间,如果超过kafka的设置,那么就会触发清理机制
  • 根据Topic存储的消息大小,如果消息大小差过一定阈值,就是出发清理机制

通过log.retention.bytes 和 log.retention.hours这两个参数来控制,当满足其中任意一个条件就会触发删除操作,数据默认保留时间是7天,触发了清理机制后,kafka会在后台启动一个线程,定期检查是否可以清楚消息,这样通过LogSegment文件达到更加细粒度的清理目标。

posted @ 2021-12-27 16:08  SyrupzZ  阅读(303)  评论(0)    收藏  举报