如何进行时序数据库InfluxDB的存储机制解析

发布时间:2021-12-28 15:43:03 作者:柒染
来源:亿速云 阅读:445

本篇文章给大家分享的是有关如何进行时序数据库InfluxDB的存储机制解析,小编觉得挺实用的,因此分享给大家学习,希望大家阅读完这篇文章后可以有所收获,话不多说,跟着小编一起来看看吧。

InfluxDB 的存储机制解析

下面介绍了InfluxDB对于时序数据的存储/索引的设计。由于InfluxDB的集群版已在0.12版就不再开源,因此如无特殊说明,所介绍对象都是指 InfluxDB 单机版

1. InfluxDB 的存储引擎演进

尽管InfluxDB自发布以来历时三年多,其存储引擎的技术架构已经做过几次重大的改动, 以下将简要介绍一下InfluxDB的存储引擎演进的过程。

1.1 演进简史

1.2 演进的考量

InfluxDB的存储引擎先后尝试过包括LevelDB, BoltDB在内的多种方案。但是对于InfluxDB的下述诉求终不能完美地支持:

此外,出于技术栈的一致性以及部署的简易性考虑(面向容器部署),InfluxDB团队希望存储引擎 与 其上层的TSDB引擎一样都是用GO编写,因此潜在的RocksDB选项被排除

基于上述痛点,InfluxDB团队决定自己做一个存储引擎的实现。

2 InfluxDB的数据模型

在解析InfluxDB的存储引擎之前,先回顾一下InfluxDB中的数据模型。

在InfluxDB中,时序数据支持多值模型,它的一条典型的时间点数据如下所示:

图 1
如何进行时序数据库InfluxDB的存储机制解析cdn.com/bceda83d3c4545a140d99a319188448dfe2193f6.png">

此外,在InfluxDB中,measurement的概念之上还有一个对标传统DBMS的 Database 的概念,逻辑上每个Database下面可以有多个measurement。在单机版的InfluxDB实现中,每个Database实际对应了一个文件系统的 目录

2.1 Serieskey的概念

InfluxDB中的SeriesKey的概念就是通常在时序数据库领域被称为 时间线 的概念, 一个SeriesKey在内存中的表示即为下述字符串(逗号和空格被转义)的 字节数组(github.com/influxdata/influxdb/model#MakeKey())

{measurement名}{tagK1}={tagV1},{tagK2}={tagV2},...

其中,SeriesKey的长度不能超过 65535 字节

2.2 支持的Field类型

InfluxDB的Field值支持以下数据类型:

DatatypeSize in MemValue Range
Float8 bytes1.797693134862315708145274237317043567981e+308 ~ 4.940656458412465441765687928682213723651e-324
Integer8 bytes-9223372036854775808 ~ 9223372036854775807
String0~64KBString with length less than 64KB
Boolean1 bytetrue 或 false

在InfluxDB中,Field的数据类型在以下范围内必须保持不变,否则写数据时会报错 类型冲突

同一Serieskey + 同一field + 同一shard

2.3 Shard的概念

在InfluxDB中, 能且只能 对一个Database指定一个 Retention Policy (简称:RP)。通过RP可以对指定的Database中保存的时序数据的留存时间(duration)进行设置。而 Shard 的概念就是由duration衍生而来。一旦一个Database的duration确定后, 那么在该Database的时序数据将会在这个duration范围内进一步按时间进行分片从而时数据分成以一个一个的shard为单位进行保存。

shard分片的时间 与 duration之间的关系如下

Duration of RPShard Duration
< 2 Hours1 Hour
>= 2 Hours 且 <= 6 Months1 Day
> 6 Months7 Days

新建的Database在未显式指定RC的情况下,默认的RC为 数据的Duration为永久,Shard分片时间为7天

注: 在闭源的集群版Influxdb中,用户可以通过RC规则指定数据在基于时间分片的基础上再按SeriesKey为单位进行进一步分片

3. InfluxDB的存储引擎分析

时序数据库的存储引擎主要需满足以下三个主要场景的性能需求

  1. 大批量的时序数据写入的高性能

  2. 直接根据时间线(即Influxdb中的 Serieskey )在指定时间戳范围内扫描数据的高性能

  3. 间接通过measurement和部分tag查询指定时间戳范围内所有满足条件的时序数据的高性能

InfluxDB在结合了1.2所述考量的基础上推出了他们的解决方案,即下面要介绍的 WAL + TSMFile + TSIFile的方案

3.1 WAL解析

InfluxDB写入时序数据时为了确保数据完整性和可用性,与大部分数据库产品一样,都是会先写WAL,再写入缓存,最后刷盘。对于InfluxDB而言,写入时序数据的主要流程如同下图所示:

图 2
如何进行时序数据库InfluxDB的存储机制解析

时序数据的WAL

由于InfluxDB对于时序数据的写操作永远只有单纯写入,因此它的Entry不需要区分操作种类,直接记录写入的数据即可

图 4
如何进行时序数据库InfluxDB的存储机制解析

其特点是在一个TSMFile中将 时序数据(i.e Timestamp + Field value)保存在数据区;将Serieskey 和 Field Name的信息保存在索引区,通过一个基于 Serieskey + Fieldkey构建的形似B+tree的文件内索引快速定位时序数据所在的 数据块

注: 在当前版本中,单个TSMFile的最大长度为2GB,超过时即使是同一个Shard,也会继续新开一个TSMFile保存数据。本文的介绍出于简单化考虑,以下内容不考虑同一个Shard的TSMFile分裂的场景

其中 **索引条目** 在InfluxDB的源码中被称为`directIndex`。在TSMFile中,索引块是按照 Serieskey + Fieldkey **排序** 后组织在一起的。

明白了TSMFile的索引区的构成,就可以很自然地理解InfluxDB如何高性能地在TSMFile扫描时序数据了:

1. 根据用户指定的时间线(Serieskey)以及Field名 在 **索引区** 利用二分查找找到指定的Serieskey+FieldKey所处的 **索引数据块**
2. 根据用户指定的时间戳范围在 **索引数据块** 中查找数据落在哪个(*或哪几个*)**索引条目**
3. 将找到的 **索引条目** 对应的 **时序数据块** 加载到内存中进行进一步的Scan

*注:上述的1,2,3只是简单化地介绍了查询机制,实际的实现中还有类似扫描的时间范围跨索引块等一系列复杂场景*

<br>

3.3 TSIFile解析

有了TSMFile,第3章开头所说的三个主要场景中的场景1和场景2都可以得到很好的解决。但是如果查询时用户并没有按预期按照Serieskey来指定查询条件,而是指定了更加复杂的条件,该如何确保它的查询性能?通常情况下,这个问题的解决方案是依赖倒排索引(Inverted Index)。

InfluxDB的倒排索引依赖于下述两个数据结构

它们在内存中展现如下:

图 7
如何进行时序数据库InfluxDB的存储机制解析

图 8

但是在实际生产环境中,由于用户的时间线规模会变得很大,因此会造成倒排索引使用的内存过多,所以后来InfluxDB又引入了 TSIFile

TSIFile的整体存储机制与TSMFile相似,也是以 Shard 为单位生成一个TSIFile。

以上就是如何进行时序数据库InfluxDB的存储机制解析,小编相信有部分知识点可能是我们日常工作会见到或用到的。希望你能通过这篇文章学到更多知识。更多详情敬请关注亿速云行业资讯频道。

推荐阅读:
  1. InfluxDB如何使用
  2. InfluxDB学习之InfluxDB的基本操作

免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。

influxdb 数据库

上一篇:如何进行FaultWrapper解析

下一篇:怎么用MINA、Netty、Twisted来实现消息分割

相关阅读

您好,登录后才能下订单哦!

密码登录
登录注册
其他方式登录
点击 登录注册 即表示同意《亿速云用户服务条款》