海量时序数据低成本存储架构设计

导读

近些年来得益于传感器技术、无线网络技术、云计算和人工智能技术的发展,物联网的基础设施日益完善,并应用到了新能源、智能家居、车联网、智慧工业等众多领域中,实现了“人与物”、“物与物”之间的互联。物联网给各行各业带来红利的同时,也给当前的技术带来了巨大的挑战,其中最关键的就是数据规模的急剧增长。根据 IDC 报告,到 2025 年物联网数据规模将达到 79.4 ZB,寻找合适的物联网数据存储解决方案自然变得非常重要。本文将结合物联网的数据特点和业务特性来解读如何降低数据存储成本,以及对比业内一些时序数据存储的实现方式。

物联网存储场景

物联网数据的产生是基于传感器采集的设备状态、事件、消息等数据,设备根据自身的类型使用对应的物联网通信协议接入到数据网关(IoT 网关),最后转发到存储,这是物联网数据流转到存储的通用链路。但是由于这些数据的应用场景不同,决定了其对存储架构的需求差异。例如业务上如果存储的是设备最新状态信息,那么每台设备只会对应一行设备状态数据(元数据),这个数据量级是由设备数决定的,一般在百万级,对于存储的需求更偏向于支持高 TPS 和索引能力。

另一种场景是业务上存储的是设备所有历史状态或者历史事件数据,那么设备数与数据量是 1 对 N 的关系,数据总量与设备数和存储时间范围正相关。以车辆轨迹数据存储为例,每辆汽车间隔一段时间就会上报一个 GPS 点,那么就需要存储一段时间内所有车辆上报的历史坐标,用于查看行车轨迹和位置,通常这类数据被称为时间序列数据(Timeseries Data)。时序数据的特点与访问模式都与传统互联网数据有非常大的差异,这导致其对于存储架构有着特殊的要求。

时序数据特点和读写模式

在解读时序数据存储架构之前,首先需要了解一下时序数据的一些概念和特点。通常来说,一个经典的时序数据模型包括:数据源(datasource),标签(tags),时间戳(timestamp),度量指标(mertics)。数据源 + 标签表示独立的时间线,数据源 + 标签 + 时间戳表示独立的时间点。

例如我们构造了一组时序数据样例,将其映射到二维表结构上如下图所示,图中包含了三组时间线,每一个时间线代表了设备个体的历史数据变化。其中数据源(datasource)和 tags(标签)用于区分设备,不同的设备型号的度量指标(mertics)不一样。

海量时序数据低成本存储架构设计_第1张图片

从中可以总结出如下几个特点:

  1. 数据源唯一

时序数据总是由固定设备产生,不同设备之间产生数据的过程相互独立。这一点对于数据的访问性能和存储空间都有着非常大的优化空间。

  1. 指标维度多

物联网设备种类非常复杂,每种类型的设备度量指标大不一样,例如 A 类型设备上报的是温度、湿度,而 B 类型设备上报的是压力值。存储所有设备的度量指标所需要定义的字段会达到几十个甚至上百个,且会动态增加。如果使用关系型数据库来存储,则需要根据字段数的动态变化频繁修改数据表 schema,这显然是不能接受的。如果按照设备类型分表存储,那么当业务上对多种类型设备聚合分析时,就需要多表 join,这不仅会提高业务代码的复杂度,同时会降低查询的性能。

  1. 时间顺序产生

时序数据是按照固定的周期或者是某个事件触发上报的,每一行时序数据都会带有数据上报时间戳 timestamp 属性。通常情况下,同一个设备下的时序数据是按照时间递增的,并且很少会有更新某一行时序数据的请求。

  1. 数据冷热明显

业务上更多关注的是设备最近一段时间的状态,例如查询车辆近一段时间的轨迹,而很少会查询一年前的车辆轨迹。时序数据的价值会随着时间推移而降低,因此距离当前时间越近的数据访问频率要远高于时间更早的数据。

  1. 多维度聚合分析

时序数据的业务场景中经常存在面向时间范围的多维度交互查询和聚合分析。以上图数据为例:分析一个月内 model = "A 的所有设备平均温度。这类分析请求包含了多条时间线。

时序数据存储如何设计

基于上述对时序数据特点和业务读写模式的分析,可以给出时序数据存储的设计目标:大规模低成本数据存储、高 TPS 写入、高效数据分析。要实现这几个目标,可以从 更细粒度的资源控制、更低单价的存储介质、更高的数据压缩率、更高的副本利用率 四个方向进行优化。

01. 更细的资源控制粒度

资源可以分为存储资源和计算资源。要实现对资源更细粒度的控制,就需要将计算层与存储层解耦。首先我们来看一下几种存储计算架构。

单机架构

海量时序数据低成本存储架构设计_第2张图片

单点架构是最简单的一种存储架构,单台机器节点上包含了存储服务和磁盘,所有的读写请求都会发送到一台机器上。当机器出现故障时,整个存储服务将变为不可用的状态,这无法满足不了时序数据存储的可用性需求。

分布式存算耦合

海量时序数据低成本存储架构设计_第3张图片

为了解决存储服务的可用性问题,可以采用主从集群架构。写入请求先发送到主节点(primary node)上,再基于分布式一致性协议将数据全量同步到其他节点中,这样可以保证存储服务的可用性和可靠性。但是从成本角度分析,假设每个节点都是写入本地磁盘,在不考虑节点内数据冗余的情况下,则需要分别预留三份存储资源和计算资源。

分布式存算分离

海量时序数据低成本存储架构设计_第4张图片

计算层。计算层是一组无状态节点组成的集群,具有更好的可扩展性。计算层分离还有一个好处是,由于时序数据的读写是相对不均衡的,写入流量是取决于设备数和上报周期,基本是稳定的;而读取流量取决于业务,存在一定的波动性。这就可以将计算层按照读和写进一步分离,可以做到为读取和写入分别预留适当的计算资源。

存储层。存储层选择分布式存储,例如 HDFS、对象存储等。同时可以按照时序数据的访问特性进行分层存储,将不同时间段的数据分别存储到单价不同的存储介质中,做到精细化存储。

02. 更低单价的存储

区分冷热数据

近期写入的时序数据我们可以将其看作为热数据(Hot Data),而写入时间更早的数据我们可以看作为冷数据(Cold Data)。热数据具有高 TPS、写入时间近的特点,通常用于高频的单个时间线查询,例如查询某台车辆近期的行驶轨迹;冷数据具有规模大、极少修改、写入时间早的特点,通常用于低频的多个时间线交互式分析,例如计算某个型号所有设备的平均能耗值。

时序数据的访问频率会随着时间推移呈现出由热到冷的趋势,正是由于不同时间范围的时序数据访问特性不一样,对于底层存储的性能要求也有所差异。利用这一点可以描绘出一个数据分层存储架构。

分层存储

存储优化的思路是对时序数据分层存储。结合上述不同时间范围的时序数据访问频率的差异,存储层可以采用多种存储介质和存储方式来分别负责热数据和冷数据的存储,从而在保证性能的同时最大化地降低存储成本。

存储单价按照由高到低可以分为固态硬盘(SSD)、混合硬盘(HHD)、机械硬盘(HDD),另外还包括存储密度更大、单价更低的对象存储(Object Store)。

由于热数据对于存储的性能要求较高,通常可以使用 SSD 或 HHD 存储。而冷数据的规模很大,更多关注的是存储成本的大小,那么存储单价更低的对象存储更为合适。如下图展示了时序数据分层存储的架构:

海量时序数据低成本存储架构设计_第5张图片

数据存储格式

冷热数据的业务访问模式决定了适用的存储格式,常见的数据存储格式分为基于行的存储和基于列的存储。

热数据的读写模式包括高并发写入、小范围扫描,这个场景行存储更为合适。行存储的优点是磁盘的单个块中可能包含整行所有字段,查询整行数据时有利于减少范围查询时的磁盘 I/O 次数。存储侧基于 LSM 引擎,利用了磁盘顺序写性能大于随机写性能的特点,提高写入速度。

海量时序数据低成本存储架构设计_第6张图片

冷数据基本不会更新,业务查询的方式通常是多个时间线的交互分析,这一特性非常适合采用按列组织存储。列存是面向读优化的(Read-Optimized),适用于数据分析的场景。时序场景中经常会分析设备的一些指标,例如求和、求均值等,如果采用行存储,则会读取到其他不参与计算的列,这将会降低分析性能。而列存格式可以避免扫描非相关列的问题,多个列的数据分析可以并行执行。另外列存格式数据之间的相关性更高,这意味着列存数据可以有更高的压缩率,有利于降低存储量,也能降低分析时的 I/O 量。

海量时序数据低成本存储架构设计_第7张图片

03. 更高的数据压缩率

时序数据采用列存格式存储,数据之间的相关性较高,这就可以采用数据编码和压缩算法对设备上报的原始数据进行压缩,使得最终存储的数据量减少。一些时序数据库内置的压缩功能可以将数据量压缩到十倍甚至二十倍以上,从而降低存储成本。例如同一个设备上报的数据必然会包含设备元属性的冗余,例如上文提到的 datasource、tags 等,重复存储这些数据会浪费大量的存储资源,那么就可以针对这部分数据做一个去重优化。再比如时序数据中的 timestamp 属性,同一个设备上报的 timestamp 相对而言有比较明显的规律,下面我们以二阶差分编码(delta-of-delta)对时间戳的压缩举例:

delta-of-delta 算法

时序数据中每一个数据点(一行数据)都会包含时间戳字段,如果按照时间戳的原始值进行存储,那么每一个时间戳值都会占用 64 bit,这则会造成存储成本的增加。我们知道对于同一时间线的时序数据中的 timestamp 值都是顺序递增的,并且非常可能是以等差数列增长(取决于设备上报周期)。利用这一特点,可以采用数值压缩算法(delte-of-delta)来对时间戳进行压缩,本质上是存储两行数据之间的时间戳差值,这个存储大小将远远小于原始值。例如下图展示了存储原始时间戳和压缩后的时间戳,所占用的空间大小对比:

存储格式

原始时间戳

delta (最大范围阀值 127)

delta-of-delta

存储值

1658214010922

0

0

1658214010932

10

10

1658214010942

10

0

1658214010952

10

0

1658214010972

20

10

存储大小

64 * 5 = 320 bit

64 + 5 * 9 = 109 bit

64 + 1 * 3 + 2 * 9 = 85 bit

可以看出经过 delta-of-delta 编码压缩后的存储大小相对于原始的数据大小下降了三倍以上,事实上时序数据库都会采用例如 XOR、Delta、Zigzag 等算法对不同数据类型的原始数据进行压缩编码,从而达到降低存储空间和成本的目的,数据压缩率也成为了衡量一款时序数据存储产品性能的指标之一。

04. 更高的副本空间利用率

副本机制是保证数据高可靠的方案,副本的数量是影响时序数据存储成本的重要因素之一。常规的做法是使用三副本来保证数据的可靠性,但是这种方式实际上只有一份数据会被使用到,得盘率仅有 33.3%。而使用纠删码(Erasure-Code)可以大大得提高得盘率,减少实际存储的副本大小。例如采用“ EC 8+2”的得盘率能够提高到 80%,关于 EC 的原理不在本文做介绍。由于 EC 机制会将数据拆分到多个 block 中存储,那么当对小块数据随机读写时,就需要同时读写多个 block,这会造成 I/O 放大的问题,但是对于大块数据顺序读写场景,多个 block 并发读写能够提升性能。时序数据场景中,都会基于 LSM 引擎将随机写优化成顺序写,并且数据落盘前都会合并成一个大的数据块,这一特点可以避免 EC 机制带来的问题。所以通过 EC 来保证时序数据的可靠性,能在保证性能的同时减少存储成本。

总结

物联网中时序数据具有规模大、更新少、冷热明显等特点,这决定了其如何被高效地存储和分析。我们可以从业内常见的时序数据存储设计选择上做分析。例如 DB-Engines 时序数据库系列排行第一的产品 InfluxDB,其本身是仅支持本地盘存储的,是一种明显的存算耦合架构,存储上无法做到灵活选择。2020 年 InfluxDB 官方宣布重构底层存储引擎,推出新时序存储项目 InfluxDB_IOx,设计上对资源重新分配、存储层选择本地盘 + AWS S3 混存,这正是上述设计思路的体现(感兴趣的读者可以阅读 InfluxDB IOx 解析)。再例如阿里云表格存储 Tablestore 2022 年正式商业化的物联网存储 IoTstore,选择读、写、存储三层分离架构,依托云原生的 Serverless 属性,相对于开源时序存储具备资源弹性控制的成本优势。同时 IoTstore 将时序数据进一步按时间范围划分成热、温、冷数据,采用行列混存设计,底层选择多级分层存储,实现存储粒度上精确切分。除了上述的产品外,业内还有许多其他各具特色的时序存储产品,下图做了一个简单的归纳:

时序存储

存储架构

冷热存储

高可靠策略

数据压缩

InfluxDB

存算耦合

不支持

/

支持

表格存储 Tablestore

存算分离

支持

EC

支持

AWS Timestream

存算分离

支持

多副本

支持

OpenTSDB

存算分离

不支持

EC

支持

时序数据存储基于存储计算分离、冷热分层存储、数据压缩、EC 等技术方向进行优化,以达到更细资源控制粒度、更多层级的冷热存储、更高的数据压缩率、更高的副本利用率的目的。这些时序存储设计更多的是成本与性能之间的考量。

转载自:微信公众号 - 物联网存储 IoTstore

原文链接:海量时序数据低成本存储架构设计

你可能感兴趣的:(时序数据库,物联网,NoSQL,时序数据库,物联网,nosql)