72.简单介绍一下如何读取数据?
如果我们要读取第 911 条数据。
首先第一步,找到它是属于哪一段的,根据二分法查找到他属于的文件,找到
0000900.index
和00000900.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 之数据存储》 文章。