序言
笔者在平时工作中时时都在享受kafka的性能和稳定性,但始终没有机会真正了解kafka的设计思想和设计原理,最近报名了极客时间的一门课,开始坚持阅读kafka源代码。在此期间我也会持续更新自己梳理注释过的源代码。
鉴于本人的Scala代码能力有限,加上kafka的代码层次较深,在阅读源码的初期我会忽略一些kafka复杂设计的细节以及嵌套过深的方法调用,先从最核心的最小单元类开始,之后自己有了更全面的把握之后会有更全面的分析总结。
一点源码相关信息
本次源码阅读的是kafka的主分支, kafka主分支
ide采用Intellij idea,编译工具gradle版本6.3。
Log与LogSegment
kafa的源码中设计最丰富也最精妙的是server端或者说啥broker端的代码,而kafka和众多消息系统不同的地方在于kafka传输的消息是需要持久化的,这一特点在很大程度上造就kafka的容错性。
正如kafka官方所指出的:
As a result of taking storage seriously and allowing the clients to control their read position, you can think of Kafka as a kind of special purpose distributed filesystem dedicated to high-performance, low-latency commit log storage, replication, and propagation.
kafka从文件系统的角度来看是一个专注于提交日志存储、复制和增长的分布式文件系统。从某种程度上来说,kafka的日志部分上kafka所有上层系统的基石,也是最直接和系统相关的部分。掌握这一部分的源码能够很有效提高我们对于kafka存储功能的理解,对于kafka broker在文件系统上创建的文件的意义和作用,对于kafka的使用中可能出现的日志问题会有更清晰的解决思路。
首先来看一下Log对象,如下可见官网的截图:
![](https://i-blog.csdnimg.cn/blog_migrate/f1829a7f1ae2287a279974b9138c727b.png)
kafka主题的一个分区对应一个Log对象,生产者会按顺序向指定的分区追加日志消息。如果我们只关注单个分区内消息的追加过程:
![](https://i-blog.csdnimg.cn/blog_migrate/996837b2e7949d0d780df0aa1e0c1a46.png)
上图所示的是官网对于kafka log的抽象图,事实上真正的日志的管理远比示意图复杂,图中的一个个位移数值代表的也不是简单的一条消息,而是日志段,消息会追加入对应的日志段,而日志段之间的位移保持有序,因此消息之间的保持有序。
![](https://i-blog.csdnimg.cn/blog_migrate/301f119b4525538c21d962f0e7066957.png)
每一个分区中的消息以Log的形式存在,但Log并不是日志存储和操作的最底层单元,kafka消息最底层的单元的是日志段,即LogSegemnt, Log和LogSegement的关系如上图所示。
这里需要注意的是,kafka的日志段并不是一个物理概念,而是一个逻辑概念,一个日志段包括一个消息日志文件和若干索引文件组成,即一个.log和多个.xxxindex文件:
![](https://i-blog.csdnimg.cn/blog_migrate/88208d6df9a1f1c4aaaf377bb4623180.png)
如图是笔者刚执行了kafka官方的quickstart之后的topic对应文件夹(因为新增的test主题设置为单分区,故只有一个分区文件夹,该文件夹下所有的文件对应一个Log)下的文件,因为笔者用生产者产生的消息条数很少,所以生成了一个日志段,故topic文件夹下只有一个对应日志段,