
正如 InfluxDB 文档所说:
InfluxDB actually looks like two databases in one, a time series data store and an inverted index for the measurement, tag, and field metadata.
InfluxDB 保存着时序数据,以及时序数据的倒排索引。
TSM
时序数据使用类似 LSM Tree 的 TSM Tree (Time Series Merge Tree)存储,而且是一种「列式」存储结构。
数据写入时:
- 先保存到 cache 和 WAL 当中
- 当 WAL 当中数据超出阈值时,将 WAL 文件写入到 level 1 的 TSM 文件当中,cache 和 WAL 也随之清空
- 每个 TSM 文件主要分成两部分:时序数据,以及时序数据的索引,通过索引可以使用二分查找找到我们需要的数据
- 随着 TSM 文件变多,系统会将多个小 的TSM 文件会合并成一个的更大的 TSM 文件,持续这个过程保证文件数量不会过多
TSM 文件的合并策略是比较老的 size-tiered 策略,将小的文件压缩成大的文件,这一点和 leveldb 不太一样,leveldb 要严格保证每个 level 下的文件没有重叠,但是 influxdb 不会。
之所以这么设计,应该是因为查询时序数据的时候,一般会根据时间进行筛选,而大部分时候每个 TSM 文件当中都是越老的文件数据也越老,数据天然会按照时间排序,虽然会有重叠的情况,但是权衡利弊,最终可以容忍这种情况,查询的时候做数据合并的成本更小。
TSI
TSI 是 Time Series Index 的缩写,influxdb 用 TSI 来保存时序数据的倒排索引。可以通过 TSI 快速查询到某个表中,包含某个 tag 的 series 都有哪些。
TSI 的另一个工作是将倒排索引保存在磁盘当中,在 TSI 之前,influxdb 完全是使用内存存储倒排索引的,当时序数据变多的时候,特别是「表」变多的时候,倒排索引消耗的内存会飙升。TSI 使用类似 TSM 的文件结构来存储索引。

查询实现
influxdb 基于 TSM 和 TSI 来提取数据,先是从 TSI 当中获取需要查询的 series,再从 TSM 文件中读取 series 当中的时序数据(points)
TSM、TSI 主要是充当存储引擎,就像 inodb 和 mysql 之间的关系。作为一个数据库,influxdb 除了使用 TSM、TSI 以外,还需要在其上层完成查询语句的语法解析、查询计划优化、查询计划执行等常规工作。
查询优化的过程包含了逻辑查询优化和物理查询优化,不过相比传统的数据库,查询优化主要是基于启发式优化规则,流程不是很复杂。这部分的实现在 flux 项目当中。