前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >图解Kafka消息是被怎么存储的?

图解Kafka消息是被怎么存储的?

作者头像
ImportSource
发布2019-05-06 15:58:29
3.9K0
发布2019-05-06 15:58:29
举报
文章被收录于专栏:ImportSourceImportSource

在本文中,我们来了解下Kafka是如何存储消息数据的。了解了这些,有助于你在遇到性能问题的时候更好地调试,让你知道每个broker配置实际上所起的作用。那么,Kafka内部的存储是什么样的呢?

Kafka以Partition作为存储单元

一个partition是一个有序的,不变的消息队列,消息总是被追加到尾部。一个partition不能被切分成多个散落在多个broker上或者多个磁盘上。

Kafka数据保留策略。你可以设置要被保留的数据量和时长,之后Kafka就会按照你的配置去清除消息数据,无论这个数据是否被消费。

Partition是由多个Segment组成

Kafka需要在磁盘上查找需要删除的消息,假设一个partition是一个单个非常长的文件的话,那么这个查找操作会非常慢并且容易出错。为解决这个问题,partition又被划分成多个segment来组织数据。

当Kafka要写数据到一个partition时,它会写入到状态为active的segment中。如果该segment被写满,则一个新的segment将会被新建,然后变成新的“active” segment。

Segment以该segment的base offset作为自己的名称。

在磁盘上,一个partition就是一个目录,然后每个segment由一个index文件和一个log文件组成。如下:

$ tree kafka | head -n 6

kafka

├── events-1

│ ├── 00000000003064504069.index

│ ├── 00000000003064504069.log

│ ├── 00000000003065011416.index

│ ├── 00000000003065011416.log

Segment下的log文件就是存储消息的地方

每个消息都会包含消息体、offset、timestamp、key、size、压缩编码器、校验和、消息版本号等。

在磁盘上的数据格式和producer发送到broker的数据格式一模一样,也和consumer收到的数据格式一模一样。由于磁盘格式与consumer以及producer的数据格式一模一样,这样就使得Kafka可以通过零拷贝(zero-copy)技术来提高传输效率。

$ bin/kafka-run-class.sh kafka.tools.DumpLogSegments --deep-iteration --print-data-log --files /data/kafka/events-1/00000000003065011416.log | head -n 4

Dumping /data/kafka/appusers-1/00000000003065011416.log

Starting offset: 3065011416

offset: 3065011416 position: 0 isvalid: true payloadsize: 2820 magic: 1 compresscodec: NoCompressionCodec crc: 811055132 payload: {"name": "Travis", msg: "Hey, what's up?"}

offset: 3065011417 position: 1779 isvalid: true payloadsize: 2244 magic: 1 compresscodec: NoCompressionCodec crc: 151590202 payload: {"name": "Wale", msg: "Starving."}

索引(Index)

Segment的index负责映射消息offset到某个消息在log文件中的位置。如下:

索引文件是内存映射(memory mapped)的,offset查找使用二分查找来查找小于或等于目标offset的最近offset。

有关内存映射:

即便是顺序写入硬盘,硬盘的访问速度还是不可能追上内存。所以Kafka的数据并不是实时的写入硬盘,它充分利用了现代操作系统分页存储来利用内存提高I/O效率。 Memory Mapped Files(后面简称mmap)也被翻译成内存映射文件,它的工作原理是直接利用操作系统的Page来实现文件到物理内存的直接映射。完成映射之后你对物理内存的操作会被同步到硬盘上(操作系统在适当的时候)。通过mmap,进程像读写硬盘一样读写内存,也不必关心内存的大小有虚拟内存为我们兜底。 mmap其实是Linux中的一个用来实现内存映射的函数,在Java NIO中可用MappedByteBuffer来实现内存映射。 为什么Kafka那么快,作者:fireflyc

索引文件由8个字节的条目组成,4个字节用来存储相对于base offset的偏移量,另外4个字节用来存储position。这个偏移量由于是相对于base offset的,因此只需要4个字节来存储。比如base offset是10000000000000000000,那么接下来就不用存储为10000000000000000001 和10000000000000000002了,而是仅存储为1和2。

Kafka消息压缩

生产者发送压缩消息,是把多个消息批量发送,把多个消息压缩成一个wrapped message来发送。和普通的消息一样,在磁盘上的数据和从producer发送来到broker的数据格式一模一样,发送给consumer的数据也是同样的格式。

回顾

现在你已知道Kafka存储内部是如何工作的了:

• Partition是Kafka的存储单元。

• Partition被分成多个segment。

• Segment包含两个文件:index和log文件。

• Index负责映射每个offset到消息的在log文件中的具体位置,主要用来查找消息。

• Indexes 保存的是当前segment的base offset的相对偏移量。

• 压缩消息批量发送是被包装一个wrapper message来发送。

• 保存在磁盘上的数据格式和broker从producer收到的以及发送给consumer的数据格式一模一样,这样就能够实现领拷贝(zero-copy)。

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2019-03-18,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 ImportSource 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
相关产品与服务
对象存储
对象存储(Cloud Object Storage,COS)是由腾讯云推出的无目录层次结构、无数据格式限制,可容纳海量数据且支持 HTTP/HTTPS 协议访问的分布式存储服务。腾讯云 COS 的存储桶空间无容量上限,无需分区管理,适用于 CDN 数据分发、数据万象处理或大数据计算与分析的数据湖等多种场景。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档