Kafka索引

只要是用于写入、查询的数据,都会考虑有一些索引结构。 比如说MySQL的B+树,Redis的跳表,Kafka也是如此,Kafka的索引类似于 Java 中的跳跃表 ConcurrentSkipListMap 的结构。

索引存储结构和文件

一个Topic分为多个Partition,分布在多台节点(物理机或者虚拟机)上。一个Partition分为多个Segment。

每个Segment对应三个文件:偏移量索引文件、时间戳索引文件、消息存储文件,索引文件后缀是 .log 文件和 .index 文件。

index 和 log 文件以当前 segment 的第一条消息的 offset 命名,形如

00000000000000000000.index

00000000000000000000.log

00000000000000000000.timeindex



00000000000000239430.index

00000000000000239430.log

00000000000000239430.timeindex

Kafka 中的索引文件以稀疏索引(sparse index)的方式构造消息的索引,它并不保证每个消息在索引文件中都有对应的索引项,也就是说offset是不连续的,是一个区间范围。

索引项中没有直接使用绝对偏移量而改为只占用 4 个字节的相对偏移量(relativeOffset = offset - baseOffset),这样可以减小索引文件占用的空间。

查找动作

先用二分法在偏移量索引文件查找索引,然后从日志分段文件中的物理位置 xxx 开始顺序查找偏移量为 N 的消息。

Kafka 的每个日志对象中使用了 ConcurrentSkipListMap 来保存各个日志分段,每个日志分段的 baseOffset 作为 key,这样可以根据指定偏移量来快速定位到消息所在的日志分段。

Kafka和MySQL的索引区别

InnoDB中维护索引的代价比Kafka中的要高。

Kafka中当有新的索引文件建立的时候 ConcurrentSkipListMap 才会更新,而不是每次有数据写入时就会更新,Kafka中的索引文件顺序追加文件的操作,和B+树比起来工作量要小很多。

B+树中数据有插入、更新、删除的时候都需要更新索引,还会引来“页分裂”等相对耗时的操作。

MySQL中需要频繁地执行CRUD的操作,CRUD是MySQL的主要工作内容,为了支撑CRUD,需要使用维护量大很多的B+树去支撑。

Kafka中的消息一般都是顺序写入磁盘,再到从磁盘顺序读出(不深入探讨page cache等),主要工作内容就是:写入+读取,很少有检索查询的操作

检索查询只是Kafka的一个辅助功能,不需要为了这个功能而去花费特别太的代价去维护。

Kafka中的这种方式是在磁盘空间、内存空间、查找时间等多方面之间的一个折中。

投资随笔

最近,关于房地产开发公司的暴雷很多,其实从2021年恒大暴雷开始,房地产就开始走下坡路了。

关于暴雷,我们每次都认为,只有银行、地产、保险、信托等金融或者类金融机构才有暴雷的说法,一般公司经营不善都认为是倒闭,所以暴雷是对于有杠杆的金融机构的说法,因为有杠杆,所以风险高,所以监管是必须的。

大部分时候,对高杠杆的行业和公司,多考虑考虑一下,是很有必要的。