写点什么

OpenMetric 与时序数据库模型之主流 TSDB 分析

发布于: 3 小时前

​​​​摘要:为大家带来当下时序数据模型的主流 TSDB 分析及云厂商在时序数据模型方面的最新动态。


本文分享自华为云社区《【万字干货】OpenMetric与时序数据库存储模型分析(下)》,作者:敏捷的小智 。

 

在上篇《【万字干货】OpenMetric与时序数据库存储模型分析(上)》文章中,我们了解了时序数据模型的相关知识内容,接下来为大家分析当下主流 TSDB 及云厂商在书序数据模型方面的最新动态。

主流 TSDB 分析

InfluxDB


InfluxDB[9]是一个一站式的时序工具箱,包括了时序平台所需的一切:多租户时序数据库、UI 和仪表板工具、后台处理和监控数据采集器。如下图 9 所示。


图 9


InfluxDB 支持动态 shcema,也就是在写入数据之前,不需要做 schema 定义。因此,用户可以随意添加 measurement、tag 和 field,可以是任意数量的列。


InfluxDB 底层的存储引擎经历了从 LevelDB 到 BlotDB,再到自研 TSM 的历程。从 v1.3 起,采用的是基于自研的 WAL + TSMFile +TSIFile 方案,即所谓的 TSM(Time-StructuredMerge Tree)引擎。其思想类似 LSM,针对时序数据的特性做了一些特殊优化。TSM 的设计目标一是解决 LevelDB 的文件句柄过多问题,二是解决 BoltDB 的写入性能问题。


Cache: TSM 的 Cache 与 LSM 的 MemoryTable 类似,其内部的数据为 WAL 中未持久化到 TSM File 的数据。若进程故障 failover,则缓存中的数据会根据 WAL 中的数据进行重建。


WAL (WriteAhead Log) : 时序数据写入内存之后按照 SeriesKey 进行组织。数据会先写入 WAL,再写入 memory-index 和 cache,最后刷盘,以保证数据完整性和可用性。基本流程包括:根据 Measurement 和 TagKV 拼接出乎 series key;检查该 series key 是否存在;如果存在,就直接将时序数据写入 WAL、时序数据写缓存;如果不存在,就会在 Index WAL 中写入一组 entry;依据 series key 所包含的要素在内存中构建倒排索引、接着把时序数据写入 WAL 和缓存。


TSM Files: TSM File 与 LSM 的 SSTable 类似。在文件系统层面,每一个 TSMFile 对应了一个 Shard,单个最大 2GB。一个 TSM File 中,有存放时序数据(i.e Timestamp + Field value)的数据区,有存放 Serieskey 和 Field Name 信息的索引区。基于 Serieskey +Fieldkey 构建的形似 B+tree 的文件内索引,通过它就能快速定位到时序数据所在的数据块。在 TSMFile 中,索引块是按照 Serieskey + Fieldkey 排序 后组织在一起的。


TSI Files:用户如果没有按预期根据 Series key 来指定查询条件,比如指定了更加复杂的查询条件,技术手段上通常是采用倒排索引来确保它的查询性能的。由于用户的时间线规模会变得很大,会造成倒排索引消耗过多的内存。对此 InfluxDB 引入了 TSIfiles。TSIFile 的整体存储机制与 TSMFile 相似,也是以 Shard 为单位生成一个 TSIFile。


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


InfluxDB 作为时序数据库,必然包括时序数据存储和一个用于度量、标记和字段元数据的倒排索引,以提供更快速的多维查询。InfluxDB 在 TSMFile 上按照下面的步骤扫描数据,以获得高性能查询效果:


  • 根据用户指定的时间线(Serieskey)和 FieldKey 在索引区找到 Serieskey+FieldKey 所在的 索引数据块。

  • 根据用户指定的时间戳范围在索引数据块中查找数据对应在哪个或哪几个索引条目

  • 把检索出的索引条目所对应的时序数据块加载到内存中进一步扫描获得结果


和 Prometheus 一样,InfluxDB 数据模型有键值对作为标签,称为标签。InfluxDB 支持分辨率高达纳秒的时间戳,以及 float64、int64、bool 和 string 数据类型。相比之下,Prometheus 支持 float64 数据类型,但对字符串和毫秒分辨率时间戳的支持有限。InfluxDB 使用日志结构合并树的变体来存储带有预写日志,按时间分片。这比 Prometheus 的每个时间序列的仅附加文件方法更适合事件记录。

Prometheus


下图是 Prometheus 官方架构图[10],包括了一部分生态组件,它们大多是可选项。其中最核心的是 Prometheus 服务器,它负责抓取和存储时间序列数据,并对这些数据应用规则,从而聚合出新的时间序列或生成警报,并记录存储它们。


图 10


TSDB 是 Prometheus 的关键内核引擎。最新的 V3 引擎[7]相当于面向 TSDB 场景优化后的 LSM(Log Structured Merge Tree,结构化合并树)。LSM 树核心思想的核心就是放弃部分读能力,换取写入的最大化能力;其假设前提就是内存足够大。通常 LSM-tree 适用于索引插入比检索更频繁的应用系统。V3 存储引擎也采用了 Gorilla 论文思想。它包括了下面几个 TSDB 组件:块头(Head Block)、预写日志 WAL 及检查点、磁盘上 Chunk 头的内存映射、持久化 block 及其索引和查询模块。下图 11 是 Prometheus 的磁盘目录结构。


图 11


在 V3 引擎中一个 chunk 内会包含很多的时间线(Time series)。Chunk 目录下的样本数据分组为一个或者多个段(segment),每个缺省不超过 512MB。index 是这个 block 下的 chunk 目录中的时间线按照指标名称和标签进行索引,从而支持根据某个 label 快速定位到时间线以及数据所在的 chunk。meta.json 是一个简单的关于 block 数据和状态的一个描述文件。Chunks_head 负责对 chunk 索引,uint64 索引值由文件内偏移量(下 4 个字节)和段序列号(上 4 个字节)组成。


Prometheus 将数据按时间维度切分为多个 block。只有最近的一个 block 允许接收新数据。最新的 block 要写入数据,会先写到一个内存结构中,为了保证数据不丢失,会先写一份预写日志文件 WAL,按段(大小 128MB )存储在目录中。它们是未压缩的原始数据,因此文件大小明显大于常规块文件。Prometheus 将保留三个或者多个 WAL 文件,以便保留至少两个小时的原始数据。


V3 引擎将 2 个小时作为块(block)的默认块持续时间;也就是块按 2h 跨度来分割(这是个经验值)。V3 也是采用了 LSM 一样的 compaction 策略来做查询优化,把小的 block 合并为大的 block。对于最新的还在写数据的 block,V3 引擎则会把所有的索引全部 hold 在内存,维护一个内存结构,等到该 block 关闭再持久化到文件。针对内存热数据查询,效率非常高。


Prometheus 官方再三强调了它的本地存储并不是为了持久的长期存储;外部解决方案提供延长的保留时间和数据持久性。社区有多种集成方式尝试解决这个问题。比如 Cassandra、DynamoDB 等。

通过指标实现应用的可观察性(observability)是 IT 监控运维系统的第一步。指标提供汇总视图,再结合日志提供的有关每个请求或事件的明细信息。这样更容易帮助问题的发现与诊断。


Prometheus 服务器彼此独立运行,仅依赖其本地存储来实现其核心功能:抓取、规则处理和警报。也就是说,它不是面向分布式集群的;或者说当前它的分布式集群能力是不够强大的。社区的 Cortex、Thanos 等开源项目就是针对 Prometheus 的不足而涌现出来的成功解决方案。

Druid


Druid[11]是有名的实时 OLAP 分析引擎。Druid 的架构设计比较简洁(如下图 12)。集群中节点分 3 类:Master 节点、Query 节点和 Data 节点。


图 12


Druid 数据存储在 datasource 中,类似于传统 RDBMS 中的表(table)。每个 datasource 都按时间(其他属性也可以)分区(partition)。每个时间范围称为一个“块(Chunk)”(例如,一天,如果您的数据源按天分区)。在一个 Chunk 内,数据被分成一个或多个 “段(Segment)”。每个段都是一个文件,通常包含多达几百万行数据。如下图 13 所示。


图 13


Segment 的目的在于生成紧凑且支持快速查询的数据文件。这些数据在实时节点 MiddleManager 上产生,而且可变的且未提交的。在这个阶段,主要包括了列式存储、bitmap 索引、各种算法进行压缩等。这些 Segment(热数据)会被定期提交和发布;然后被写入到 DeepStorage(可以是本地磁盘、AWS 的 S3,华为云的 OBS 等)中。Druid 与 HBase 类似也采用了 LSM 结构,数据先写入内存再 flush 到数据文件。Druid 编码是局部编码,是文件级别的。这样可以有效减小大数据集合对内存的巨大压力。这些 Segment 数据一方面被 MiddleManager 节点删除,一方面被历史节点(Historical)加载。与此同时,这些 Segment 的条目也被写入元数据(Metadata)存储。Segment 的自描述元数据包括了段的架构、其大小及其在深度存储中的位置等内容。这些元数据被协调器(Coordinator)用来进行查询路由的。


Druid 将其索引存储在按时间分区的 Segment 文件中。Segment 文件大小推荐在 300MB-700MB 范围内。Segment 文件的内部结构,它本质上是列存的:每一列的数据被布置在单独的数据结构中。通过单独存储每一列,Druid 可以通过仅扫描查询实际需要的那些列来减少查询延迟。共有三种基本列类型:时间戳列、维度列和指标列,如下图 14 所示:


图 14


维度(Dimension)列需要支持过滤和分组操作,所以每个维度都需要以下三种数据结构:

1) 将值(始终被视为字符串)映射到整数 ID 的字典,

2) 列值的列表,使用 1 中的字典编码。 【服务于 group by 和 TopN 查询】

3) 对于列中的每个不同值,一个指示哪些行包含该值的位图(本质就是倒排索引,inverted index)。【服务于快速过滤,方便 AND 和 OR 运算】


Druid 中每列存储包括两部分:Jackson 序列化的 ColumnDescriptor 和该列的其余二进制文件。 Druid 强烈推荐默认使用 LZ4 压缩字符串、long、float 和 double 列的值块,使用 Roaring 压缩字符串列和数字空值的位图。尤其在高基数列场景中匹配大量值的过滤器上 Roaring 压缩算法要快得多(对比 CONCISE 压缩算法)。


值得一提的是 Druid 支持 Kafka Indexing Service 插件(extension),实现实时摄入(ingestion)任务,那么此时可以立即查询该 segment,尽管该 segment 并没有发布(publish)。这更能满足对数据的产生到可查询可聚合分析的实时性要求。


Druid 另外一个重要特性就是在数据写入的时候,可以开启 rollup 功能,将选定的所有 dimensions 按照你指定的最小时间间隔粒度(比如 1 分钟,或者 5 分钟等)进行聚合。这样可以极大的减少需要存储的数据大小,缺点是原始的每条数据就被丢弃了,不能进行明细查询了。


Druid 为了让查询更高效,有如下设计考虑。


  • Broker 修剪每个查询访问哪些 Segment:它是 Druid 限制每个查询必须扫描的数据量的重要方式。首先查询先进入 Broker,Broker 将识别哪些段具有可能与该查询有关的数据。然后,Broker 将识别哪些 Historian 和 MiddleManager 正在为这些段提供服务,并向这些进程中的每一个发送重写的子查询。Historical/MiddleManager 进程将接收查询、处理它们并返回结果。Broker 接收结果并将它们合并在一起以获得最终答案,并将其返回给原始调用者。

  • Segment 内利用索引过滤:每个 Segment 内的索引结构允许 Druid 在查看任何数据行之前确定哪些(如果有)行与过滤器集匹配。

  • Segment 内只读取特定关联的行和列:一旦 Druid 知道哪些行与特定查询匹配,它只会访问该查询所需的特定列。在这些列中,Druid 可以从一行跳到另一行,避免读取与查询过滤器不匹配的数据。


时间戳也是 Druid 数据模型的必备项。尽管 Druid 不是时序数据库,但它也是存储时序数据的自然选择。Druid 数据模型可以支持在同一个 datasource 中,可以同时存放时序数据和非时序数据。因此,Druid 不认为数据点是“时间序列”的一部分,而是将每个点单独处理以进行摄入和聚合。比如正统的 TSDB 支持的时序数据插值计算,在 Druid 中就不复存在的必要了。这会给一些业务场景的处理带来很大的便利性。

IoTDB


Apache IoTDB[12]始于清华大学软件学院,2020 年 9 月为 Apache 孵化器项目。IoTDB 是一个用于管理大量时间序列数据的数据库,它采用了列式存储、数据编码、预计算和索引技术,具有类 SQL 的接口,可支持每秒每节点写入数百万数据点,可以秒级获得超过数万亿个数据点的查询结果。主要面向工业界的 IoT 场景。


IoTDB 套件由若干个组件构成,共同形成数据收集、数据摄入、数据存储、数据查询、数据可视化、数据分析等一系列功能。如下图 15 所示:


图 15


IoTDB 特指其中的时间序列数据库引擎;其设计以设备、传感器为核心,为了方便管理和使用时序数据,增加了存储组(storage group 的概念)。


存储组(Storage Group): IoTDB 提出的概念,类似于关系数据库中的 Database 的概念。一个存储组中的所有实体的数据会存储在同一个文件夹下,不同存储组的实体数据会存储在磁盘的不同文件夹下,从而实现物理隔离。对 IoTDB 内部实现而言,存储组是一个并发控制和磁盘隔离的单位,多个存储组可以并行读写。对用户而言,方便了对设备数据的分组管理和方便使用。


设备 (Device):对应现实世界中的具体物理设备,比如飞机发动机等。在 IoTDB 中, device 是时序数据一次写入的单位,一次写入请求局限在一个设备中。


传感器(Sensor): 对应现实世界中的具体物理设备自身携带的传感器,例如:风力发电机设备上的风速、转向角、发电量等信息采集的传感器。在 IoTDB 中,Sensor 也称为测点(Measurement)。

测点/物理量(Measurement,也称工况、字段 field):一元或多元物理量,是在实际场景中传感器采集的某时刻的测量数值,在 IoTDB 内部采用<time, value>的形式进行列式存储。 IoTDB 存储的所有数据及路径,都是以测点为单位进行组织。测量还可以包含多个分量(SubMeasurement),比如 GPS 是一个多元物理量,包含 3 个分量:经度、维度、海拔。多元测点通常被同时采集,共享时间列。


IoTDB 的存储由不同的存储组构成。每个存储组是一个并发控制和资源隔离单位。每个存储组里面包括了多个 Time Partition。其中,每个存储组对应一个 WAL 预写日志文件和 TsFile 时序数据存储文件。每个 Time Partition 中的时序数据先写入 Memtable,同时记入 WAL,定时异步刷盘到 TsFile。这就是所谓的 tLSM 时序处理算法。


摄入性能方面:IoTDB 具有最小的写入延迟。批处理大小越大,IoTDB 的写入吞吐量就越高。这表明 IoTDB 最适合批处理数据写入方案。在高并发方案中,IoTDB 也可以保持吞吐量的稳定增长(受网卡、网络带宽约束)。


聚合查询性能方面:在原始数据查询中,随着查询范围的扩大,IoTDB 的优势开始显现。因为数据块的粒度更大,列式存储的优势体现出来,所以基于列的压缩和列迭代器都将加速查询。在聚合查询中,IoTDB 使用文件层的统计信息并缓存统计信息。多个查询只需要执行内存计算,聚合性能优势明显。

数据存储对比


基于前面的分析,我们尝试用下面的表格对比来说明这些时序数据处理系统的特点。


表 3


对于时序数据的处理,关键能力主要包括数据模型定义、存储引擎、与存储紧密协作的查询引擎和支持分区扩展的架构设计。主流的 TSDB 基本都是基于 LSM 或者结合时序数据场景专门优化的 LSM tree 来实现(包括 InfluxDB 号称的 TSM,IoTDB 的 tLSM,本质上都还是 LSM 机制)。其中只有 IoTDB 独创采用了 tree schema 来对时序数据建模。为了追求极致性能和极致成本,大家都在针对海量数据和使用场景,持续改进和优化数据的存储结构设计、各种高效索引机制、和查询效率。从单点技术或者关键技术上来讲,有趋同性和同质化的大趋势。

云厂商最新动态


除了开源社区推陈出新外,国内外众多云服务厂商也陆续发布了相关的时序数据库产品或者服务。

华为云


华为云的 GaussDB for Influx[13]云服务,基于 InfluxDB 进行深度优化改造,在架构、性能和数据压缩等方面进行了技术创新,取得了很好的效果。实现了存储与计算分离架构,其中采用了华为云自研的高性能分布式存储系统,显著提升了时序数据库的可靠性;同时方便计算节点分钟级扩容和存储空间的秒级扩容,同时大幅降低存储成本。支持亿级时间线(开源的能力在千万时间线级别),写入性能基本保持稳定;能够支持更高的高散列聚合查询性能;在压缩算法上,相比原生的 InfluxDB,重点针对 Float、String、Timestamp 这三种数据类型进行了优化和改进。


华为云 MRS 云服务包含了 IoTDB[14],其中 IoTDB 定位为面向工业设备、工业现场的时序数据库库。IoTDB 优化后性能更好,千万级数据点秒级写入,TB 级数据毫秒级查询;优化后的数据压缩比可达百倍,进一步节省存储空间和成本;通过采用对等分布式架构,双层多 Raft 协议,边云节点同步双活,做到 7*24 小时高可用。在工业化场景,真正做到一份时序数据兼容全场景、一套时序引擎打通云边端和一套框架集成云边端。

阿里云


据公开资料[15],阿里云时序时空数据库 TSDB 的发展演变经历了三个阶段。在 v1.0 阶段基于 OpenTSDB,底层实现了双引擎——HBase 和 HiStore。在 v2.0 阶段中,把 OpenTSDB 引擎换成了自研的 TSDB 引擎,弥补了 OpenTSDB 不支持的倒排索引、面向时序场景的特殊编码、分布式流计算聚合函数等特性。随后实现了云和边缘计算一体化,TSQL 兼容 Prometheus 生态。其中 TSDB for Spatial Temporal 支持时空数据,它基于自研的 S3 时空索引和高性能电子围栏。最新 TSDB 同样基于 Gorilla, 将单个数据点的平均使用存储空间降为 1~2 个字节,可以降低 90%存储使用空间,同时加快数据写入的速度。对于百万数据点的读取,响应时间小于 5 秒,且最高可以支撑每秒千万数据点的写入。相较于开源的 OpenTSDB 和 InfluxDB,读写效率提升了数倍,同时兼容 OpenTSDB 数据访问协议。

腾讯云


腾讯云也推出了 TencentDB for CTSDB[16]云服务,它是一款分布式、可扩展、支持近实时数据搜索与分析的时序数据库,兼容 Elasticsearch 常用的 API 接口和生态。它支撑了腾讯内部 20 多个核心业务。性能方面可以做到每秒千万级数据点写入,亿级数据秒级分析。CTSDB 也是采用 LSM 机制,先写内存再周期性刷写到存储;然后通过倒排索引加速任意维度数据查询,能实现数据秒级可查。也支持像 histogram、percentile、cardinality 这样的通用聚合计算函数;也通过配置 Rollup 任务定时聚合历史数据保存至新的数据表,实现降精度(Downsampling)特性。在集群中节点数量超过 30 个时,需要新购集群或者将通用集群架构优化升级为混合节点集群架构,以保证多节点超大集群的性能稳定。从这些特性推断,CTSDB 内核应该是借鉴了 ElasticSearch 内核深度优化经验的基础上构建的时序数据库能力。

国内其他厂商


除了云服务厂商提供的开箱即用的云服务外,还有一些创新型产品涌现出来,比较有名的包括 TDengine[17]、字节跳动的 TerarkDB[18]、DolphinDB[19]等等。他们也在快速演进发展中,值得大家持续跟踪关注,尤其是国内孵化出来的一些 TSDB 产品。

总结与展望


InfluxDB、IoTDB 和 OpenTSDB 等除了社区版本外,也有云厂商提供原生 InfluxDB(阿里云 TSDB for InfluxDB)、IoTDB(华为云 MRS IoTDB)或 OpenTSDB(华为云 MRS OpenTSDB)云化服务,方便使用。更主流的做法是各云厂商根据自身的技术沉淀和研发实力,借鉴、优化甚至重新研发了时序数据库内核,能提供更强的集群能力,更高性能写入,更快的查询和聚合分析能力。国外厂商 AWS 有 Timestream[20],一种 Serverless 时序数据库服务,国内华为云的 GaussDB for Influx,汇聚顶级数据库专家团队打造的新一代时空分析数据库;腾讯云的 TencentDB for CTSDB,兼容 ES 生态;阿里云的 HiTSDB 等等。这些开箱即用的、可扩展的、高可用的时序数据库,为云原生应用的开发与部署带来了福音,无需管理底层基础设施,只需专注于业务构建。


Promeheus 发展过程中,其需要长期保存的历史数据(long-term)存储是其短板之一。业界有一些折中的集成方案。比如采用 Cassandra 作为 Prometheus 的持久化存储;还有采用 InfluxDB 作为 Prometheus 的持久化存储,一方面充分利用 Prometheus 监控相关能力和社区生态(包括支持分布式集群的 Cortex);另一方面利用好 InfluxDB 时序数据库优点,尤其是超 PB 级的分布式数据库能力,以弥补 Prometheus 在海量历史数据存储上的短板。


Apache Druid 在 OLAP 即时分析领域有着很强的竞争力,也为众多大厂所采用。业界最大的集群拥有 4000 多个节点。不管是时序指标,还是业务数据,应用日志等,都可以利用 Druid 的 Kafka IndexingService 和其强大的数据预处理能力,转换为时序数据进入 Druid。目前 Druid SQL 特性发展也很快,包括跨表 join,subquery 和众多函数、算子的持续丰富。


不管是正统的时序数据库,还是适合时序数据的 OLAP 分析系统;不管是开源社区的热门项目,还是云厂商提供更强大的云原生时序数据库,都为各种时序数据(包括指标、业务数据)的存储、检索和分析提供多样化的选择。用户结合自己的业务场景,一定能找到相对适合的工具或服务,满足业务诉求。

参考资料


[9]    https://www.influxdata.com/products/influxdb/

[10]    https://prometheus.io/docs/introduction/overview/

[11]    https://druid.apache.org/docs/latest/design/architecture.html

[12]    https://iotdb.apache.org/SystemDesign/Architecture/Architecture.html

[13]    https://bbs.huaweicloud.com/blogs/252115

[14]    https://bbs.huaweicloud.com/blogs/280948

[15]    https://developer.aliyun.com/article/692580

[16]    https://cloud.tencent.com/developer/article/1010045

[17]    https://www.taosdata.com/cn/

[18]    https://github.com/bytedance/terarkdb

[19]    https://www.dolphindb.cn/

[20]    https://aws.amazon.com/cn/timestream


点击关注,第一时间了解华为云新鲜技术~

发布于: 3 小时前阅读数: 4
用户头像

提供全面深入的云计算技术干货 2020.07.14 加入

华为云开发者社区,提供全面深入的云计算前景分析、丰富的技术干货、程序样例,分享华为云前沿资讯动态,方便开发者快速成长与发展,欢迎提问、互动,多方位了解云计算! 传送门:https://bbs.huaweicloud.com/

评论

发布
暂无评论
OpenMetric与时序数据库模型之主流TSDB分析