引子

之所以写这篇文章是因为之前面试时候被面试官问到(倒)了,面试官说:“你说你对Kafka比较熟?看过源码? 那说说kafka日志段如何读写的吧?”

我心里默默的说了句 “擦…我说看过一点点源码,不是亿点点。早知道不提这句了!”,那怎么办呢,只能回家等通知了啊。

但是为了以后找回场子,咱也不能坐以待毙,日拱一卒从一点点到亿点点。今天我们就来看看源码层面来Kafka日志段的是如何读写的。

Kafka的存储结构

总所周知,Kafka的Topic可以有多个分区,分区其实就是最小的读取和存储结构,即Consumer看似订阅的是Topic,实则是从Topic下的某个分区获得消息,Producer也是发送消息也是如此。

topic-partition关系

上图是总体逻辑上的关系,映射到实际代码中在磁盘上的关系则是如下图所示:

每个分区对应一个Log对象,在磁盘中就是一个子目录,子目录下面会有多组日志段即多Log Segment,每组日志段包含:消息日志文件(以log结尾)、位移索引文件(以index结尾)、时间戳索引文件(以timeindex结尾)。其实还有其它后缀的文件,例如.txnindex、.deleted等等。篇幅有限,暂不提起。

以下为日志的定义

以下为日志段的定义

indexIntervalBytes可以理解为插了多少消息之后再建一个索引,由此可以看出Kafka的索引其实是稀疏索引,这样可以避免索引文件占用过多的内存,从而可以在内存中保存更多的索引。对应的就是Broker 端参数log.index.interval.bytes 值,默认4KB。

实际的通过索引查找消息过程是先通过offset找到索引所在的文件,然后通过二分法找到离目标最近的索引,再顺序遍历消息文件找到目标文件。这波操作时间复杂度为O(log2n)+O(m),n是索引文件里索引的个数,m为稀疏程度。

这就是空间和时间的互换,又经过数据结构与算法的平衡,妙啊!

再说下rollJitterMs,这其实是个扰动值,对应的参数是log.roll.jitter.ms,这其实就要说到日志段的切分了,log.segment.bytes,这个参数控制着日志段文件的大小,默认是1G,即当文件存储超过1G之后就新起一个文件写入。这是以大小为维度的,还有一个参数是log.segment.ms,以时间为维度切分。

那配置了这个参数之后如果有很多很多分区,然后因为这个参数是全局的,因此同一时刻需要做很多文件的切分,这磁盘IO就顶不住了啊,因此需要设置个rollJitterMs,来岔开它们。

怎么样有没有联想到redis缓存的过期时间?过期时间加个随机数,防止同一时刻大量缓存过期导致缓存击穿数据库。看看知识都是通的啊!

日志段的写入

1、判断下当前日志段是否为空,空的话记录下时间,来作为之后日志段的切分依据

2、确保位移值合法,最终调用的是AbstractIndex.toRelative(..)方法,即使判断offset是否小于0,是否大于int最大值。

3、append消息,实际上就是通过FileChannel将消息写入,当然只是写入内存中及页缓存,是否刷盘看配置。

4、更新日志段最大时间戳和最大时间戳对应的位移值。这个时间戳其实用来作为定期删除日志的依据

5、更新索引项,如果需要的话(bytesSinceLastIndexEntry > indexIntervalBytes)

最后再来个流程图

消息写入流程

日志段的读取

1、根据第一条消息的offset,通过OffsetIndex找到对应的消息所在的物理位置和大小。

2、获取LogOffsetMetadata,元数据包含消息的offset、消息所在segment的起始offset和物理位置

3、判断minOneMessage是否为true,若是则调整为必定返回一条消息大小,其实就是在单条消息大于maxSize的情况下得以返回,防止消费者饿死

4、再计算最大的fetchSize,即(最大物理位移-此消息起始物理位移)和adjustedMaxSize的最小值(这波我不是很懂,因为以上一波操作adjustedMaxSize已经最小为一条消息的大小了)

5、调用 FileRecords 的 slice 方法从指定位置读取指定大小的消息集合,并且构造FetchDataInfo返回

再来个流程图:

消息读取流程

小结

从哪里跌倒就从哪里爬起来对吧,这波操作下来咱也不怕下次遇到面试官问了。

区区源码不过尔尔,哈哈哈哈(首先得要有气势)

实际上这只是Kafka源码的冰山一角,长路漫漫。虽说Kafka Broker都是由Scala写的,不过语言不是问题,这不看下来也没什么难点,注释也很丰富。遇到不知道的语法小查一下搞定。

所以强烈建议大家入手源码,从源码上理解。今天说的 append 和 read 是很核心的功能,但一看也并不复杂,所以不要被源码这两个字吓到了。

看源码可以让我们深入的理解内部的设计原理,精进我们的代码功力(经常看着看着,我擦还能这么写)。当然还有系统架构能力。

然后对我而言最重要的是可以装逼了(哈哈哈)。

情景剧

老白正目不转睛盯着监控大屏,“为什么?为什么Kafka Broker物理磁盘 I/O 负载突然这么高?”。寥寥无几的秀发矗立在老白的头上,显得如此的无助。

“是不是设置了 log.segment.ms参数 ?试试 log.roll.jitter.ms吧”,老白抬头间我已走出了办公室,留下了一个伟岸的背影和一颗锃亮的光头!

“我变秃了,也变强了”

面试官:你对Kafka比较熟? 那说说kafka日志段如何读写的吧?相关推荐

  1. 面试官:看你简历写了熟悉Kafka,它为什么速度会这么快?

    前言 Kafka的消息是保存或缓存在磁盘上的,一般认为在磁盘上读写数据是会降低性能的,因为寻址会比较消耗时间,但是实际上,Kafka的特性之一就是高吞吐率. 即使是普通的服务器,Kafka也可以轻松支 ...

  2. 2020我也当了面试官-java面试题之一

    2020我也当了面试官-java面试题之一 写在前面   最近一段时间开始帮团队招聘一些1-3年的java开发人员,参与几场下来,发现有些面试官问的问题虽然基础,我却记忆有些模糊.大概是平常CRUD太 ...

  3. 网站二次开发如何防止别人打包源码_面试官:你说你对Kafka比较熟?看过源码吗?...

    Kafka是一个分布式的,支持多分区.多副本的分布式消息流平台,同时也是一款开源的基于发布订阅模式的消息引擎系统,其最大的特点就是收发消息非常快,Kafka每秒可以处理几十万条消息,最低延迟也只有几毫 ...

  4. 面试官问:Kafka 会不会丢消息?怎么处理的?

    点击上方蓝色"方志朋",选择"设为星标" 回复"666"获取独家整理的学习资料! Kafka存在丢消息的问题,消息丢失会发生在Broker, ...

  5. 面试官问:为什么MySQL的索引不采用Kafka的索引机制

    点击上方"方志朋",选择"设为星标" 回复"666"获取新整理的面试资料 第一眼看到这个问题,也是很迷惑的,谁没事会问这种问题.然而,事实上 ...

  6. 面试官:说说Kafka处理请求的全流程

    今天来讲讲 Kafka Broker端处理请求的全流程,剖析下底层的网络通信是如何实现的.Reactor在kafka上的应用. 再说说社区为何在2.3版本将请求类型划分成两大类,又是如何实现两类请求处 ...

  7. 干趴面试官系列 | 请你简述一下Kafka中的分区分配

    欢迎跳转到本文的原文链接:https://honeypps.com/mq/kafka-basic-knowledge-of-partition-assignors/ "请你简述一下Kafka ...

  8. kafka计算机专业读法_面试官:Kafka 为什么快?

    无论 kafka 作为 MQ 也好,作为存储层也罢,无非就是两个功能(好简单的样子),一是 Producer 生产的数据存到 broker,二是 Consumer 从 broker 读取数据.那 Ka ...

  9. 阿里大牛总结:学会这些Kafka知识,吊打面试官就是分分钟的事

    文末送个福利~ 最近一直在搞企业复工大数据监测的事情,说实话,听起来这事挺高级,挺有现代感,背后涉及到的东西很多,而且这东西也不为赚钱,就是为了出一份力,同时,还会有和XX(就是那个)的合作. 如果什 ...

最新文章

  1. java pagemodel,Java PageModel
  2. windows-服务端口
  3. tensorflow学习(1.CNN简单实现MNIST)
  4. 解决function id unknown issue
  5. Educational Codeforces Round 76 (Rated for Div. 2) E. The Contest 思维 + 差分
  6. 今天听阿里P8讲完SpringBoot,瞬间感觉自己白学了……
  7. zabbix 时间错误_监控的朋友看过来,官方社区专家开源的Zabbix报表系统
  8. 【黄金分割点】与【斐波那契数列】
  9. VBA 打开 Debug窗口 进行调试 (同时可以查看debug操作对应的快捷键)
  10. 用户已关闭隐式函数计算_针对隐式反馈和LightFM模型的杂谈
  11. 工具栏快速创建类_还费时费力找菜单栏中的工具?教你制作属于自己的快速访问工具栏...
  12. C++ 编译器生成默认构造函数的四种情况
  13. Tomcat发布项目时,浏览器地址栏图标的问题
  14. springboot+vue实现excel导入-------去重
  15. php实现答题测试功能,PHP+MySQL实现在线测试答题实例
  16. 维和医疗分队患者信息管理系统的开发与研究
  17. 学生专用计算机怎样开启关机,电脑自动关机,教您笔记本怎么设置自动关机
  18. 哈里森,史上最具空间价值的钟表匠
  19. elementUI 时间格式化
  20. 51nod 1526 分配笔名(字典树)

热门文章

  1. 图像代数运算:平均值去噪,减去背景
  2. 一直以来伴随我的一些学习习惯(四):知识结构
  3. 鸟哥的Linux私房菜(基础篇)- 鸟哥的第一本书的主要内容,以 Mandrake 9.0 为例
  4. poj 1113 Wall 凸包的应用
  5. 待删除未删除 问题解决
  6. MySQL创建函数,报错;SQL Error (1418)
  7. matlab 字符串替换
  8. webrtc 实现web端对端视频
  9. [shell] if else以及大于、小于、等于逻辑表达式
  10. linux下开启程序崩溃生成core文件开关之ulimit详解