CirroData-TimeS时序数据库的文件存储格式

业界 作者:程序猿 2022-05-26 17:11:44

CirroData-TimeS在插入性能、查询性能,以及压缩比测试中都远超InfluxDB,而其所支持的分布式时序数据库在具备高可用性的同时,性能仍能达到单机性能的80%,完全能够应对物联网大爆发的数据场景需求。

本篇将揭示CirroData-TimeS极致性能背后的核心技术之一:文件存储格式。

时序数据的特征

时序数据具有如下特征:

数据是时序的,即一定带有时间戳。由于时序数据是某个测点,或是某个事件源持续不断的产生的,产生数据的时间点对于追溯、分析这个时间下测点,事件的状态非常重要,所以时序数据一般都带有时间戳,这个是时序数据最大的特征。按时间范围读取通常来说,一般不会关心某个特定点的数据,而且关注一段时间的数据,关注这段时间之内的数据的走势。聚合查询价值高用户会对某段时间之内某些测点的一些聚合值感兴趣,比如count、avg、max、last_value、first_value等。时间序列多大千万级甚至亿级别由于入网设备的增多,测点数量增加,时间序列就会越来越多,如何管理和存储这些时间序列元信息,也是将要面临的挑战。数据量大,存储成本高由于测点数据是不间断持续写入的,随着入网设备逐渐增加,数据量将会越来越大,会占用大量的磁盘空间,这就要求时序数据库具有较高的压缩比,能够节省磁盘空间。

文件存储方式

文件存储格式主要有两类:行存和列存。

假设有如下数据。

1、行存

行存如下图所示:

每行数据连续存储行和行之间顺序存储典型的代表有Apache Avro

2、列存

列存如下图所示:

每列连续存储列和列之间顺序存储

3、行列式存储

还有一类是行列式存储,实际上是对列式文件存储格式的改进,如下图所示:

以两行为一个存储单元对数据进行切分每个存储单元内按列存储典型的代表有Apache Parquet,Apache ORC文件存储格式选择

行存储的写入是一次性完成,消耗的时间比列存储少,并且能够保证数据的完整性,缺点是数据读取过程中会产生冗余数据,如果只有少量数据,此影响可以忽略;数量大可能会影响到数据的处理效率。

列存储在写入效率、保证数据完整性上都不如行存储,它的优势是在读取过程,不会产生冗余数据,这对数据完整性要求不高的大数据处理领域,尤为重要;并且压缩效果好,能降低存储成本。

而时序数据的特性是写多读少,量大,对完整性要求不高,读取模式更多的是对某些列某段数据的读取,因此其更适合列式存储格式。

列式时序数据存储格式TsFile

TsFile(Time Series File)是CirroData-TimeS的数据文件存储格式,类似于Parquet的文件结构。分析TsFile文件格式之前,先来看下真实环境中时序数据的格式。

如下图所示,一般工厂内有多个设备(device),每个设备会有多个传感器(sensor),每个传感器会采集某种指标(measurement)。

1、数据存储方式

同一个设备(device)下的数据最好存放在一起,因为我们习惯查询一个设备的一些信息关联分析设备的情况;同一种指标(measurement)的数据最好放在一起,因为数据量会比较大(7x24小时产生),需要考虑压缩效率,同一类数据相似度比较高,有利于压缩;数据最好按时间序来存储,因为指标数据采集是源源不断的,用户查询时一般也会有监控最近一段时间,或者某段时间区间数据的需求,按时间序排序能加快查询速度。因此如下图所示,对数据进行抽象如下:

一个设备(device)下的数据隶属于一个ChunkGroup;而每个指标(measurement)的数据存储为一个Chunk;每个Chunk内数据按时间序排序,每段时间数据为一个Page。

这里把一个chunk的数据拆成多个Page是有好处的,提供更细粒度的存储抽象单元可以降低读取冗余数据的数量。

2、索引存储方式

存储完数据后,为了加快查询,一般需要建立索引,而索引越细查询越快。根据上面的数据划分,最细粒度的是Page,但是如果以Page为粒度做索引,索引的开销会很大,毕竟数据量过大,会导致大量的Page产生,索引将变得非常大,查询时如果索引无法被加载进内存,那查询效果会大打折扣。

一个比较直观的做法就是以Chunk为粒度来构建索引。因此索引树就有三层。

某个设备(device)的所有数据的索引根;某个文件多次刷写设备(device)数据的索引,因为一个设备(device)的数据可能会多次刷写到一个文件里,因此其数据会分布在文件的多个位置里,需要给这每个部分加一层索引;某个指标(measurement)的数据索引,因为一个设备(device)的数据里会包含多个传感器的数据,因此还需要给每个指标的数据加一层索引。

如果将一个设备(device)的某段时间的数据索引及其下的指标(measurement)的索引可以放在一起,查询时可以一并读出,可以减少一层索引的查找。

最终索引树如下图所示:

所有设备(device)的索引根按设备id顺序存放,其指向其数据的二级索引起始处;某个设备(device)的所有数据的索引按时间序存放,每段时间区间的数据实际上是分散在文件的多个位置;设备(device)数据索引内包含多个指标(measurement)的数据索引,按指标id顺序存放。

3、文件格式

如下图所示,TsFile文件格式分为几大块:

文件头(magic number)数据部分元数据部分(索引部分)文件尾(magic number)

3.1 文件头&文件尾

都是magic number,共12字节TsFilev0.8.0。

3.2 数据部分

ChunkGroup代表一个设备(device)的一段时间的数据,包含一系列Chunk,末尾还有一个ChunkFooter(用来记录deviceId信息);Chunk代表一个传感器一段时间的数据,包含一个ChunkHeader和一系列Page;Page代表一个传感器一小段时间的数据,包含一个PageHeader和一系列点数据。其中点数据包含是时间列和数值列,一一对应。3.3 元数据部分

ChunkGroupMetaData每个设备(device)某段时间的数据的索引,会有多个,每个下面会包含多个ChunkMetaData。ChunkMetaData:某个传感器某段时间的数据索引。

FileMetadata整个文件的元数据信息,包括设备(device)数据索引的根,指标(measurement)的元数据信息,以及一些统计数据。DeviceIndexMetadata:某个设备(device)的索引的根。MeasurementSchema当前文件的所有指标(measurement)的元数据信息。

更详细的元数据和数据信息可以看参考2。

4、优化

读取的流程如下:

读取文件元数据信息;二分查找deviceIndexMetadata,找到对应的device的ChunkGroupMetadata;读取该device下所有的ChunkMetaData到内存中;根据ChunkMetaData读取对应的数据。

实际生产过程中会遇到一个设备有几十万的传感器的情况,此时会加载大量与当前查询无关的ChunkMetaData信息,对查询性能也会有巨大的性能开销。

如何进行优化?我们会在下篇关于时序数据库CirroTimeS的文章中再继续介绍新的改进。

备注:

CirroData-TimeS时序数据库是基于开源Apache IoTDB改进、东方国信深度参与的国产时序数据库。CirroData-TimeS时序数据库团队有2名Apache IoTDB Committer。

关注公众号:拾黑(shiheibook)了解更多

赞助链接:

关注数据与安全,洞悉企业级服务市场:https://www.ijiandao.com/
四季很好,只要有你,文娱排行榜:https://www.yaopaiming.com/
让资讯触达的更精准有趣:https://www.0xu.cn/

公众号 关注网络尖刀微信公众号
随时掌握互联网精彩
赞助链接