Kafka深入解析

一、kafka存储结构

1.kafka为什么使用磁盘作为存储介质

2.分析文件存储格式

3.快速检索消息

1.kafka存储结构

Kafka 的基本存储单元是分区( partition**)**

(1)每个partition相当于一个大文件被平均分配到多个大小相等的segment段(数据文件)里,

默认情况下,每个片段包含 1GB 或一周的数据,以较小的那个为准

(2)每个patition只需要支持顺序读写即可,segment文件的生命周期由服务端配置参数决定。

它将每个 Partition 分为多个 Segment,每个 Segment 对应两个文件:".index" 索引文件和 ".log" 数据文件。

​ 这些文件位于同一文件下,该文件夹的命名规则为:topic 名-分区号。例如,first 这个 topic 有三分分区,则其对应的文件夹为 first-0,first-1,first-2。

# ls /root/data/kafka/first-0        
00000000000000009014.index    
00000000000000009014.log
00000000000000009014.timeindex
00000000000000009014.snapshot   
leader-epoch-checkpoint
2.partition中segment文件存储结构

(1)segment文件组成 :主要由2部分组成,index文件、data文件,这两个文件一一对应,成对出现,分别代表索引文件数据文件二者名称一样,仅仅只是后缀不一样,一个是.index,一个是.log

(2)segment文件命名规则:partition中第一个segment从0开始,每个segment文件名称为上一个segment文件最后一条消息的offset值。数值最大为64为long大小,19位数字字符长度,没有数字用0填充。

二、kafka日志索引

1.数据文件的分段

kafka解决查询效率的手段之一是将数据文件分段,比如有100条Message,他们的offset是从0到99的,假如数据分为5段,第一段为0-19,第二段为20-39,以此类推,这样在查找指定offset的Message时,用二分查找就可以定位到该消息再哪个段中。

2.偏移量索引

数据文件分段使得可以快速查到对应的Message,但是依旧需要扫描才能找到对应的Message。为了进一步提供查询效率,kafka为每个分段后的segment文件建立了索引文件,索引文件名称与数据文件名称都是一样的,只是扩展名为.index。

三、kafka日志清理

1.Kafka日志管理器删除策略

(1)按时间删除:目前策略是删除修改时间在N天之前的日志。

(2)按大小删除:保留最后的N GB数据。

2.超时数据的清理机制

​ 一般情况下,Kafka 会根据设置的时间保留数据,把超过时效的旧数据删除掉。

​ Kafka 通过改变主题的保留策略来满足这些使用场景 ,早于保留时间的事件会被删除, 为每个键保留最新的值, 从而达到清理的效果每个日志片段可以分为以下两个部分 :

  • 干净的部分,这些消息之前被清理过, 每个键只有一个对应的值,这个值是上一次清理时保留下来的。

  • 污浊的部分,这些消息是在上一次清理之后写入的。

清理分区

​ 为了清理分区, 清理线程会读取分区的污独部分, 并在内存里创建一个 map。 map 里的每个元素包含了消息键的散列值和消息的偏移量,键的散列值是 16B,加上偏移量总共是 24B。 如果要清理一个 1GB 的日志片段,并假设每个消息大小为 1KB,那么这个片段就包含_一百万个消息,而我们只需要用 24MB的 map 就可以清理这个片段。 (如果有重复的键, 可以重用散列项, 从而使用更少的内存。 )

四、kafka日志压缩(日志清理的一种方式)

1.日志压缩

将数据压缩,只是保留每个key最后一个版本的数据。 清理的思想就是根据 Key 的重复来进行整理,注意,它不是数据删除策略,而是类似于压缩策略,如果 key 送入了值,对于业务来说,key 的值应该是最新的 value 才有意义,所以进行清理后只会保存一个 key 的最新的 value,这个适用于一些业务场景,比如说 key 代表用户 ID,Value 用户名称,如果使用清理功能就能够达到最新的用户的名称的消息(这个功能有限,请参考使用)

2.注意

kafka默认是关闭日志压缩的,启用压缩策略,需要分两步配置:

(1)在broker中配置:log.cleaner.enable=true

(2)在Topic中配置:log.cleanup.policy=compact

五、kafka为什么要用磁盘作为存储介质

Kafka选择使用磁盘作为存储介质,主要基于以下几个方面的原因:

1. 顺序读写优化
  • 顺序写入速度快:磁盘的顺序读写性能远高于随机读写。Kafka在设计时采用了文件追加的方式来写入消息,即只能在日志文件的尾部追加新的消息,并且不允许修改已写入的消息,这种方式属于典型的顺序写盘操作,能够充分发挥磁盘顺序写入的性能优势。
  • 操作系统优化:操作系统可以对顺序读写进行深层次的优化,如预读(read-ahead)和后写(write-behind)技术,进一步提升读写效率。
2. 页缓存和mmap技术
  • 页缓存:Kafka大量使用了操作系统的页缓存机制。页缓存将磁盘中的数据缓存到内存中,减少对磁盘I/O的操作。当进程需要读取磁盘上的文件时,如果数据已在页缓存中,则直接返回数据,避免了磁盘I/O。
  • mmap(内存映射文件):Kafka通过mmap技术将磁盘文件映射到内存中,用户可以通过修改内存来修改磁盘文件,提高了数据的读写效率。
3. 避免JVM内存和系统内存之间的复制
  • 减少性能开销:直接使用磁盘进行存储,避免了数据在JVM内存和系统内存之间的复制,减少了性能的创建对象和垃圾回收的开销。
4. 高效的数据管理和查询
  • 数据文件分段:Kafka将topic中的一个partition大文件分成多个小文件段(segment),通过多个小文件段,容易定期清除或删除已经消费完的文件,减少磁盘占用。
  • 索引机制:为了提高查询效率,Kafka为每个分段后的数据文件建立了索引文件。索引文件中包含索引条目,每个条目表示数据文件中一条消息的索引,包括相对offset和position,通过索引可以快速定位消息。
5. 可靠性和持久性
  • 数据持久化:Kafka将消息持久化到磁盘,即使Kafka服务重启,页缓存还是会保持有效,而进程内的缓存却需要重建。这极大地简化了代码逻辑,并提高了数据的可靠性和持久性。
  • 多副本机制:Kafka通过数据的复制机制,确保了在某些节点出现故障的情况下,系统依然能够正常工作,不会丢失数据。

综上所述,Kafka选择使用磁盘作为存储介质,主要是因为磁盘的顺序读写性能优异、页缓存和mmap技术提高了数据读写效率、避免了JVM内存和系统内存之间的复制开销、实现了高效的数据管理和查询机制,以及提供了可靠的数据持久化和多副本机制。这些因素共同使得Kafka成为一个高性能、高可靠性的消息系统。

相关推荐
小光学长几秒前
基于vue框架的的流浪宠物救助系统25128(程序+源码+数据库+调试部署+开发环境)系统界面在最后面。
数据库·vue.js·宠物
零炻大礼包1 小时前
【SQL server】数据库远程连接配置
数据库
不能再留遗憾了1 小时前
RabbitMQ 高级特性——消息分发
分布式·rabbitmq·ruby
zmgst1 小时前
canal1.1.7使用canal-adapter进行mysql同步数据
java·数据库·mysql
随心............1 小时前
python操作MySQL以及SQL综合案例
数据库·mysql
€☞扫地僧☜€1 小时前
docker 拉取MySQL8.0镜像以及安装
运维·数据库·docker·容器
茶馆大橘1 小时前
微服务系列六:分布式事务与seata
分布式·docker·微服务·nacos·seata·springcloud
CopyDragon1 小时前
设置域名跨越访问
数据库·sqlite
xjjeffery1 小时前
MySQL 基础
数据库·mysql
写bug的小屁孩1 小时前
前后端交互接口(三)
运维·服务器·数据库·windows·用户界面·qt6.3