72.简单介绍一下如何读取数据?

如果我们要读取第 911 条数据。

  • 首先第一步,找到它是属于哪一段的,根据二分法查找到他属于的文件,找到 0000900.index00000900.log 之后。

  • 然后,去 .index 中去查找 (911-900) =11 这个索引或者小于 11 最近的索引,在这里通过二分法我们找到了索引是 [10,1367]

    • 10 表示,第 10 条消息开始。
    • 1367 表示,在 .log 的第 1367 字节开始。

    ? 所以,本图的第 911 条的“1360”是错的,相比“1367” 反倒小了。

  • 然后,我们通过这条索引的物理位置 1367 ,开始往后找,直到找到 911 条数据。

上面讲的是如果要找某个 offset 的流程,但是我们大多数时候并不需要查找某个 offset ,只需要按照顺序读即可。而在顺序读中,操作系统会对内存和磁盘之间添加 page cahe ,也就是我们平常见到的预读操作,所以我们的顺序读操作时速度很快。但是 Kafka 有个问题,如果分区过多,那么日志分段也会很多,写的时候由于是批量写,其实就会变成随机写了,随机 I/O 这个时候对性能影响很大。所以一般来说 Kafka 不能有太多的Partition 。针对这一点,RocketMQ 把所有的日志都写在一个文件里面,就能变成顺序写,通过一定优化,读也能接近于顺序读。

并且,截止到 RocketMQ4 版本,索引文件,对每个数据文件中的消息,都有对应的索引。这个是和 Kafka 的稀疏索引不太一样的地方。

更详尽的,推荐阅读 《Kafka 之数据存储》 文章。