时间序列索引 (TSI) 详情
此页面记录了早期版本的 InfluxDB OSS。InfluxDB OSS v2 是最新的稳定版本。请参阅 InfluxDB v2 文档。
当 InfluxDB 摄取数据时,我们不仅存储值,还索引 measurement 和标签信息,以便可以快速查询。在早期版本中,索引数据只能存储在内存中,但是,这需要大量 RAM,并限制了一台机器可以容纳的序列数量。此上限通常在 1 到 4 百万个序列之间,具体取决于所使用的机器。
开发时间序列索引 (TSI) 是为了让我们能够突破该上限。TSI 将索引数据存储在磁盘上,因此我们不再受 RAM 的限制。TSI 使用操作系统的页面缓存将热数据拉入内存,让冷数据保留在磁盘上。
启用 TSI
要启用 TSI,请在 InfluxDB 配置文件 (influxdb.conf
) 中设置以下行
index-version = "tsi1"
(请务必包含双引号。)
InfluxDB Enterprise
要转换您的数据节点以支持 TSI,请参阅升级 InfluxDB 企业版集群。
有关配置的详细信息,请参阅配置 InfluxDB 企业版集群。
InfluxDB OSS
- 有关配置的详细信息,请参阅配置 InfluxDB OSS。
工具
influx_inspect dumptsi
如果您正在排除索引问题,可以使用 influx_inspect dumptsi
命令。此命令允许您打印索引、文件或一组文件的摘要统计信息。此命令一次仅适用于一个索引。
有关此命令的详细信息,请参阅influx_inspect dumptsi。
influx_inspect buildtsi
如果您想将现有分片从内存索引转换为 TSI 索引,或者您有现有的 TSI 索引已损坏,则可以使用 buildtsi
命令从底层 TSM 数据创建索引。如果您有要重建的现有 TSI 索引,请首先删除分片中的 index
目录。
此命令在服务器级别工作,但您可以选择添加数据库、保留策略和分片过滤器,以仅应用于分片的子集。
有关此命令的详细信息,请参阅influx inspect buildtsi。
理解 TSI
文件组织
TSI(时间序列索引)是 InfluxDB 序列数据的基于日志结构合并树的数据库。TSI 由几个部分组成
索引:包含单个分片的整个索引数据集。
分区:包含分片数据的分片分区。
LogFile:包含新写入的序列作为内存索引,并持久化为 WAL。
IndexFile:包含从 LogFile 构建或从两个相邻索引文件合并的不可变的、内存映射的索引。
还有一个 SeriesFile,其中包含整个数据库中所有序列键的集合。数据库中的每个分片共享相同的序列文件。
写入
当写入进入系统时,会发生以下情况
- 序列被添加到序列文件,如果已存在,则查找该序列。这将返回一个自动递增的序列 ID。
- 该序列被发送到索引。索引维护现有序列 ID 的 roaring bitmap,并忽略已创建的序列。
- 该序列被哈希并发送到适当的分区。
- 分区将序列作为条目写入 LogFile。
- LogFile 将序列写入磁盘上的预写日志文件,并将序列添加到一组内存索引中。
压缩
启用压缩后,InfluxDB 每秒检查是否需要压缩。如果在 compact-full-write-cold-duration
期间(默认情况下为 4h
)没有写入,InfluxDB 将压缩所有 TSM 文件。否则,InfluxDB 将 TSM 文件分组为压缩级别(由文件压缩的次数决定),并尝试合并文件并更有效地压缩它们。
一旦 LogFile
超过阈值 (5MB
),InfluxDB 会创建一个新的活动日志文件,之前的日志文件开始压缩为 IndexFile
。第一个索引文件位于级别 1 (L1)。日志文件被视为级别 0 (L0)。索引文件也可以通过合并两个较小的索引文件来创建。例如,如果存在两个连续的 L1 索引文件,InfluxDB 会将它们合并为 L2 索引文件。
InfluxDB 优先安排压缩,使用以下准则
- 级别越低(文件压缩的次数越少),压缩它的权重就越高。
- 级别中可压缩文件越多,该级别的优先级越高。如果每个级别的文件数相等,则较低级别优先压缩。
- 如果较高级别有更多压缩候选对象,则可能会在较低级别之前压缩。InfluxDB 将收集组(要压缩到单个下一代文件中的文件集合)的数量乘以每个级别的指定权重(0.4、0.3、0.2 和 0.1),以确定压缩优先级。
重要的压缩配置设置
压缩工作负载由数据库的摄取率和以下限制配置设置驱动
cache-snapshot-memory-size
:指定在将数据写入 TSM 文件之前,write-cache
保留在内存中的大小。cache-snapshot-write-cold-duration
:如果缓存未超过cache-snapshot-memory-size
大小,则此设置指定在没有任何传入数据的情况下将数据保留在内存中的时间长度,然后将数据写入 TSM 文件。max-concurrent-compactions
:可以同时运行的压缩数。compact-throughput
:控制压缩引擎的平均磁盘 I/O。compact-throughput-burst
:控制压缩引擎的最大磁盘 I/O。compact-full-write-cold-duration
:分片在计划进行完全压缩之前必须多久未接收写入或删除。
这些配置设置对于负载不规律的系统尤其有益,限制了高使用率期间的压缩,并让压缩在较低负载期间赶上进度。在负载稳定的系统中,如果压缩干扰了其他操作,通常情况下,系统负载不足,配置更改无济于事。
读取
索引提供了几个 API 调用来检索数据集,例如
MeasurementIterator()
:返回 measurement 名称的排序列表。TagKeyIterator()
:返回 measurement 中标签键的排序列表。TagValueIterator()
:返回标签键的标签值的排序列表。MeasurementSeriesIDIterator()
:返回 measurement 的所有序列 ID 的排序列表。TagKeySeriesIDIterator()
:返回标签键的所有序列 ID 的排序列表。TagValueSeriesIDIterator()
:返回标签值的所有序列 ID 的排序列表。
这些迭代器都可以使用多个合并迭代器进行组合。对于每种类型的迭代器(measurement、标签键、标签值、序列 id),都有多种合并迭代器类型
- 合并:删除两个迭代器中的重复项。
- 相交:仅返回两个迭代器中都存在的项目。
- 差异:仅返回第一个迭代器中不存在于第二个迭代器中的项目。
例如,WHERE 子句为 region != 'us-west'
的跨两个分片操作的查询将构造一组如下所示的迭代器
DifferenceSeriesIDIterators(
MergeSeriesIDIterators(
Shard1.MeasurementSeriesIDIterator("m"),
Shard2.MeasurementSeriesIDIterator("m"),
),
MergeSeriesIDIterators(
Shard1.TagValueSeriesIDIterator("m", "region", "us-west"),
Shard2.TagValueSeriesIDIterator("m", "region", "us-west"),
),
)
Log 文件结构
日志文件只是一个 LogEntry 对象列表,按顺序写入磁盘。日志文件写入到 5MB 后,然后压缩为索引文件。日志中的条目对象可以是以下任何类型
- AddSeries
- DeleteSeries
- DeleteMeasurement
- DeleteTagKey
- DeleteTagValue
日志文件的内存索引跟踪以下内容
- 按名称的 measurement
- 按 measurement 的标签键
- 按标签键的标签值
- 按 measurement 的序列
- 按标签值的序列
- 序列、measurement、标签键和标签值的 Tombstone。
日志文件还维护序列 ID 存在和 Tombstone 的位集。这些位集与其他日志文件和索引文件合并,以在启动时重新生成完整的索引位集。
Index 文件结构
索引文件是一个不可变的文件,它跟踪与日志文件类似的信息,但所有数据都已索引并写入磁盘,以便可以直接从内存映射访问。
索引文件具有以下部分
- TagBlocks: 维护单个标签键的标签值索引。
- MeasurementBlock: 维护 measurement 及其标签键的索引。
- Trailer: 存储文件的偏移信息以及用于基数估计的 HyperLogLog 草图。
清单
MANIFEST 文件存储在索引目录中,并列出属于索引的所有文件以及应访问它们的顺序。每次发生压缩时,都会更新此文件。目录中不在索引文件中的任何文件都是正在压缩的索引文件。
FileSet
文件集是 InfluxDB 进程运行时获取的清单的内存快照。这是提供索引在某个时间点的一致视图所必需的。文件集还有助于对其所有文件进行引用计数,以便在文件的所有读取器完成操作之前,不会通过压缩删除任何文件。
此页面是否对您有帮助?
感谢您的反馈!