分享嘉宾:王怀远 阿里云 表格存储架构师
编辑整理:李瑶 DataFun
出品平台:DataFunTalk
导读: 大家好,我是王怀远,我2015年加入阿里云,一直从事表格存储的研发和架构相关工作,目前担任表格存储的架构师。我在存储和数据库领域有一些研发和架构方面的经验。
本次分享的主题是一站式物联网存储产品的架构设计,希望大家可以先回答以下几个问题:
- 第1个问题:物联网场景下的数据需求有哪些,如何分类?
- 第2个问题:如何针对物联网场景设计一款存储或数据库产品?
- 第3个问题:怎么达到成本性能相比传统方案能够优化10倍的目标,技术选型的原则和方向是什么?
本次分享侧重于技术分析,不介绍具体的产品功能。带着这3个问题,我们进入今天的分享和讨论。
今天的介绍会围绕下面四部分展开:
- 物联网存储的需求:通过分析物联网存储的场景,对场景中涉及到的数据进行分类,分析这些数据对于数据库或者存储系统的相关需求,后面我们对于解决方案和架构设计的分析也会基于这些具体的需求来展开。
- 物联网存储解决方案:介绍一些物联网场景下的存储解决方案,并由此引出为什么需要一个一站式的物联网存储产品,要实现的技术目标是什么。
- 架构设计:分析如何进行架构选型,从而实现我们对于一站式存储产品的技术目标。
- 总结
--
01 物联网储存的需求 1. 物联网数据从整体来说,对于一个物联网业务,首先要解决设备接入的问题。设备接入后,数据不断上传,存储到存储系统或者是数据库中。然后再对这些数据进行分析和可视化。
常见的物联网数据可以分为三个类别,分别是设备元数据、设备消息数据和设备时序数据。
设备元数据存储了设备的标识、属性、状态等。这部分数据可以用来进行设备管理、设备状态查询和设备圈选等。
设备的消息数据,分为上行消息和下行消息,上行消息比如设备事件的上报,下行消息比如控制指令的下发、消息推送等等。消息数据常常用队列模型来建模,每个设备可以设计两个队列用来区分上行消息和下行消息,在队列模型下,对写入同一个队列的消息天然有保序的要求,新写入的消息必须排在队列的末尾,否则可能会出现消息漏收的问题。
第三类数据是设备的时序数据,时序数据一般是这三类数据中规模最大的。常见的时序数据比如端上传感器采集的数据、设备的监控数据、设备的轨迹数据等等。这些数据很少更新,一般采用时序模型进行存储,数据规模大。
2. 对存储系统的需求首先是一些通用的要求,比如高可靠、高可用、低成本、高性能、易扩展、易运维等等。
其次,不同类型数据也有着不同的功能需求。
设备元数据的要求是需要支持多维度检索、支持灵活分析、对于地理位置相关的场景需要支持地理空间的检索能力。
消息数据的要求是要支持队列模型、支持海量数据、支持消息保序等。
时序数据的要求是支持时序数据模型、支持时间序列的元数据检索、支持数据的聚合计算等。由于时序数据存储量大,对存储成本的需求非常明显。
总结一下,物联网存储的核心需求是,在海量数据下实现极低的成本、高并发写入和查询能力、可快速分析、支持元数据高频更新和多条件检索。
--
02 物联网储存解决方案带着这些需求,我们进入第二部分,物联网存储解决方案。
1. 车联网场景例子在开源数据库或者存储系统中,单一产品很难同时满足一个物联网场景中多种不同类型数据的需求。因此,常见的物联网存储解决方案需要使用多款产品。
这里我们举一个车联网场景的例子。这个场景中也包含三类数据,第一类是车辆状态汇报,属于元数据场景,主要用于车辆圈选、车辆调度等;第二类是消息通道,属于消息数据场景,包括事件上报、控制指令、消息推送等;第三类是行驶数据,属于时序数据场景,包括行驶轨迹,以及行驶状态的一些信息,如速度、发动机参数等。
每类数据对存储都有着不同的要求。
使用开源的解决方案来解决以上三个场景需求,通常需要使用组合的解决方案。对于车辆元数据,可能会使用MySQL + Elasticsearch的方案,引入ES是为了解决多字段组合条件检索的问题。对于消息数据,使用MySQL来进行存储。时序数据,则会采用HBase,来满足高吞吐写入和大规模存储的需求。
这样的组合解决方案在架构方面有着明显不足:
- 首先是运维复杂度较高,因为要运维多个产品,并且需要维护多个产品之间的数据同步;
- 其次是扩展性差,当数据规模不断增加时,某个产品在规模和性能方面可能会出现不足,这时候又要寻找新的解决方案,如果引入新的组件也会进一步加大运维复杂度和成本;
- 最后,整个方案的成本和性能并不优,一方面是这些产品并没有针对物联网场景进行优化,另一方面是由于数据库的发展,也产生了很多新的技术。
为了解决以上问题,我们希望设计一个更适合物联网的存储产品。
2. 一站式存储解决方案设想首先,我们的目标是一个一站式的物联网存储产品。这个产品通过多模型来满足不同类型数据的需求,对外提供多种访问接口,包括标准SQL、API或SDK,另外也需要提供标准的数据订阅接口,用于数据导出和生态对接。
在内核方面,存储引擎和计算引擎应该针对物联网场景的大规模、低成本、数据分析等需求进行优化。
在生态方面,需要对接物联网生态的上下游,上游包括数据采集、写入,以及大数据分析结果表的写入。下游对接实时计算、大数据分析、BI、AI、以及一些可视化工具。
整体技术目标如下:
- 从功能方面,需要满足元数据、时序、消息三类场景,支持高并发写入和查询,支持物联网场景的分析需求。
- 从成本方面,希望存储成本相比传统解决方案能够降低90%。
- 从性能方面,希望分析性能相比传统解决方案可以提升10倍。
为什么要提出这样的目标呢?
一方面,从物联网客户的角度,数据规模在不断膨胀,如果数据增长10倍,成本也增长10倍,那么将是巨大的一笔IT支出。换个角度来说,必须存在一个成本为现有方案1/10的解决方案,才能支撑物联网数据的高速增长。
另外一方面,传统的解决方案并没有很好地利用云计算、数据库方面的一些最近的发展和技术,在成本和性能方面并不优,所以我们才提出一个更高的目标。
那么如何设计才能满足这样的成本和性能目标,这是一个长期需要讨论的话题,本次分享跟大家一起讨论一下我们在这方面的思考和经验。
--
03 架构设计 1. 时序数据特征首先,以时序场景为例,分析数据模型和特征。
以时序为例,主要有两方面原因,一方面是因为时序数据是物联网场景下占比最大的一类数据,另一方面时序数据本身也有元数据,所以针对时序数据的优化技术也可以应用到设备元数据场景中。
时序数据模型,是一个典型的时间线加多值数据点的结构。
时间线:描述产生数据的设备或者叫数据源,同时可以记录相关标签和属性。如上图表格中的前三列,第一列是度量类型,第二列是数据源标识,第三列是时间线的标签。标签是对数据源的一些描述,可以作为维度,基于标签进行聚合。
数据点:即度量值,如上图表格中的后三列,每个数据点都对应一个时间戳,每个时间可能对应单个点(单值模型)或多个点(多值模型)。
另一方面,时序数据模型是一种灵活的表结构模型。
标签可以自定义、度量点可以自定义。
灵活表结构对用户使用是非常方便的,但只有部分时序数据库是支持灵活表结构的。
时序数据模型具有以下特点:
- 首先,从写入角度,一般是由设备端按照一定频率上报数据,一般只有新增,很少更新历史数据。
- 其次,从查询角度,热数据查询频率较高,冷数据也会进行查询,频率较低,同时对热数据或冷数据都有统计分析的需求。
在进行技术架构设计时,会针对这些数据特点进行设计。
2. 车联网例子下面我们通过一个具体的例子,来分析存储产品的优化方向。这个例子主要是用来存储车辆行驶数据:
- 10W辆车,每5秒上传1条数据,200byte
- 写入:平均每秒 20000 行,约 4MB/s 流量
- 存储:每天上传约 321G 数据。数据保留5年,约 587TB
- 查询:查询一辆车一段时间的状态数据;查询最近5分钟、1小时、1天、1周、1月的所有车辆统计信息
在这个场景中,为了保障数据可靠性,需要做冗余,比如采用多副本技术,那么实际存储量就可能会达到PB级别,将会是一笔不小的存储成本。
对这个场景进行一定分析:
- 首先,该场景每秒写入流量并不高,但由于数据存储时间长,因此总存储量大,存储成本占比高。
- 其次,业务的首要需求是数据能够廉价地存下来,其次是能够查询和分析。而对于分析产生的资源开销,取决于查询请求覆盖的时间范围以及相应的数据扫描量。
那么怎么针对这个场景做优化呢?
首先,我要介绍一个数据库优化方面的经典理论,叫做读/写/存储优化的共轭关系。这个理论简单来说就是,一项技术很难同时优化读/写/存储三个方面,往往只能优化其中一个或者两个。比如面向读优化的技术,往往是对写性能不友好的。而面向写优化的技术,往往又对读性能是不友好的。有些可以同时优化读和写的技术,比如缓存技术,对存储空间又是不友好的,即需要更大的存储空间,比如我们经常说的一句话,就是用空间来换时间。因此,我们的设计原则就是要找到场景中的主要矛盾点,选择不同的技术组合。
针对上述场景,主要的优化方向在哪里呢?
前面我们已经分析过,存储成本是这个场景中成本占比最高的部分,也是用户最重要的需求。因此首要目标是面向存储优化,其次是面向读性能优化。而对于写性能,因为本身TPS不高,在这个场景中需求并不强。
下面就来分析如何进行存储成本和读性能的优化。
3. 面向存储成本的优化① 第一个问题,选择怎样的存储格式?
不同存储格式有着不同的优缺点,我们这里还是以刚才的例子为例,对比一下不同的存储格式,分析一下采用不同格式存储,最终的存储空间大小。
这个数据样例如下,每行大约200byte,包括车辆ID、里程、速度、温度、发动机状态参数等采集指标。
原始数据生成500w行,大小为975MB,大约1GB。分别采用Apache Avro和Parquet格式进行存储,其中Avro大小为265MB,相比原始优化3.7倍,Parquet大小为46MB,相比原始优化21倍。
可以看到使用不同的存储格式,有着巨大的差异。
这里简单再介绍下Avro和Parquet。
Avro是一种行存格式,相比原始格式的优势在于,Avro的schema是预先定义好的,每行只存储一个列值。同时,数字使用变长编码,相比原始数据减少了约3倍。
Parquet是一种列存格式,优化效果更加明显。列存格式为何能降低存储大小:
-
按列组织,相邻数据更具有近似性
-
** 列存编码技术**
a. RLE、DICTIONARY、DELTA、BIT-PACKING、定制编码;
b. 可直接在编码后数据上做扫描分析,性能高。 -
列存编码后,仍可用通用压缩算法进一步压缩
总结一下,使用列存技术,可以把数据从587TB减少到27TB。
套用之前的数据库优化理论,列存技术是面向存储空间优化,同时面向分析优化的一种存储结构。当然,它也有一定的劣势,比如对于写性能会增加额外开销,这种一般都是采用行模式写入,后台批量转列存的方式来优化。另外对于整行数据读取,列存会有多次IO,这个场景也相比行存有一定的劣势。
② 第二个问题,选择怎样的存储架构?
这里的存储架构选择,指的是选择存储计算耦合的架构还是存储计算分离的架构。
首先,还是对这两种架构做一下介绍。
- 存储计算耦合
计算资源和存储资源绑定
机器之间复制数据,保障数据可靠性和可用性 - 存储计算分离
计算资源和存储资源解耦
由共享存储满足数据可靠性要求
更适合云原生架构,共享存储可选择云基础服务
我们认为存储计算分离的架构是更适合物联网和大规模数据场景的:
- 云上共享存储,单位存储成本更低,规格更丰富,按量计费
- 弹性计算资源,减少闲置
- 更高可靠性和可用性
使用存计分离架构,我们预计,存储成本可以下降1/3,并且计算的弹性更好,可以降低计算成本。
③ 第三个问题,如何降低冷数据访问成本?
物联网场景下,冷数据访问频率低,很多时候只是为了归档,并不怎么查询,因此思考如何优化这部分的成本。解决方案就是将数据进行分层存储。
分层策略有如下两种:
- 基于数据时间分层
- 基于写入时间分层
分层之后我们可以做的第一个优化是,将不同层的数据采用不同介质来存储,以降低单位存储大小的成本,例如:
- SSD(TLC、QLC),HDD(PMR、SMR)
- 不同规格对象存储
另外,不同层还可以采用不同的存储格式,以平衡成本和性能的需求。
- 对于热数据,行列混存:兼顾写入、更新和查询
- 对于温数据,列存:兼顾压缩率和读取性能
- 对于冷数据,列存+更高压缩率压缩:追求极致压缩率,降低存储成本
后面在查询性能分析时,也会对不同层的存储结构选择进行分析。
总结一下,使用冷热分层技术,预计存储成本再进一步下降1/3。那么综合之前讲的存储格式优化、存储计算分离架构以及冷热分层技术,我们希望达到存储成本整体降低10倍的目的。
4. 面向读性能优化首先,我们还是分析一下物联网查询场景和特点。
下面列举了三类典型的查询模式,分别是热数据查询,数据分析和元数据检索。
- 热数据查询场景,比如查询单个或者多个设备最近一段时间的状态,可用于监控等场景。
- 数据分析场景,比如分析一段时间内所有设备的某个数据点的统计值等等,用来做报表、数据统计或者异常点筛选等,一般会查询热数据或者温数据。对于冷数据也会有分析统计需求,一般查询频率比较低。
- 元数据检索场景,一般是根据多种组合条件来检索满足条件的设备列表,有多种用途。
这三类场景对数据库的查询模式也有很大差别:
- 第一类场景的查询模式一般是点查和小范围的扫描,单个请求开销比较低,但是并发要求高,适合采用一些分布式的KV引擎技术。
- 第二类场景的查询模式一般是大量数据扫描,单个请求扫描量比较大,但并发低,延迟要求一般不高,适合采用一些分布式的OLAP引擎技术。
- 第三类场景的查询模式一般是通过灵活的组合条件做数据筛选,数据的筛选率比较低,一般是采用搜索引擎相关的技术。
综上,物联网查询的需求非常丰富,但是我们可以总结出来一些基本规律:
- 对于热数据,需要具备高并发查询和分析能力
- 对于温冷数据,查询频率低,但需要具备分析能力
- 对于元数据,需要支持多条件组合查询等灵活的检索能力
此外,还需要平衡查询性能和存储成本,不能为了满足查询需求而大幅增加整体成本。
① 第一个问题,如何在低成本存储上满足查询分析需求?
首先是分层,针对热、温、冷数据采用不同的存储格式来进行优化。
- 对于热数据,采用行列混存,这里行列混存是结合了行存和列存优势的一种存储结构,在存储空间上相比纯列存会有一些冗余。因为结合了行存和列存的优势,因此既适合点查、小范围扫描,也针对数据分析做了优化,同时也支持高并发的写入和更新。
- 对于温数据,采用纯列存存储,列存一方面压缩率有优势,另一方面也非常适合扫描和分析,可以很好的满足对温数据的分析需求。
- 对于冷数据,采用纯列存,同时进行一些参数调整、使用更高压缩率的算法,降低存储成本。
套用之前数据库优化的理论,对于热数据,采用的是空间换时间的方式,追求写性能和读性能;对于温数据,面向存储空间和读性能优化;对于冷数据,面向存储空间优化,但是会增加读的开销。
这样的存储架构,很好的满足了对于查询和分析的需求。
为了进一步优化性能,还需要存储和计算层的联合优化。这里主要讲以下几个方面:
首先,数据可以进行水平切分和垂直切分。水平切分,指的是数据可以分为不同的shard,在不同的shard查询时可以有一定的并发度,同时也可以灵活控制shard的大小。垂直切分是针对时间维度做分片。
基于这样的切分,在查询时,就可以根据时间范围和一些文件级别的统计信息来过滤掉不需要扫描的数据文件。
另一方面,整个查询需要一个分布式的执行器,从而提高查询的并发度。
另外,也可以利用云原生的能力,在需要进行大量数据分析需求之前,弹性地扩容一批机器,计算后再进行缩容。
总结一下,通过使用分层技术和采用不同存储格式,既降低了存储成本,同时也满足了查询和分析需求。另一方面,通过分布式的SQL执行能力,提升计算性能,通过云原生的存计分离架构,可以弹性的扩容计算资源。
② 第二个问题,如何进行快速的元数据检索
如何在海量的时序数据中检索时间线?
第一个方案是直接在数据上进行扫描和过滤,但是由于元数据仅占数据的一小部分,所以直接扫描的筛选率很低,效果并不好。
第二个方案就是采用倒排索引,这也是很多时序数据库都采用的方案。倒排索引的方案经常遇到的一个问题是规模问题,因为很多时序数据库的倒排索引实现是一个单机版本,并且需要加载很多索引数据到内存中,因此只能支持较小规模的时间线。
为了解决规模问题,可以采用这样的方案:
首先是元数据和数据分离存储。
其次是要采用分布式的索引技术。具体来说,就是分shard来存储索引部分,查询时查询多个shard的数据再进行合并。这样总体时间线规模可以支撑到百亿到千亿的级别,这在物联网场景下已经完全足够了。
有了元数据索引之后,在数据查询时也可以根据元数据索引进行查询优化。
这部分主要涉及计算引擎的查询优化器部分,查询优化器可以根据查询条件和索引信息,计算该查询命中的时间线数量,结合其他的统计信息,就可以计算出一个筛选率。这个筛选率表示如果进行数据扫描,有多少比例数据是满足时间线过滤条件的。根据这个筛选率可以决定查询计划是分时间线进行定位加小范围扫描,还是直接扫描数据。
总结一下,为了满足元数据检索的需求,存储引擎需要支持分布式倒排索引技术,同时计算引擎可以利用存储引擎的索引信息做查询优化,这部分查询优化的前提是需要实现一个定制化的查询优化器。
现在我们已经分析了如何优化存储成本,如何优化查询分析性能,如何优化元数据检索性能。下面我们总结一下这样一个物联网存储产品的整体架构。
5. 整体架构整体架构如下。
从访问接口和模型方面,整个架构支持多数据模型访问,包括时序、消息场景的定制模型,接口支持API、SDK接口,SQL、JDBC接口,以及数据订阅接口。
从架构方面,需要采用存储计算分离的架构,满足弹性、高可靠、易扩展,支持数据分层存储,以满足低成本的需求。
从存储引擎方面,需要支持多种存储格式,内置不同存储格式的转换和生命周期管理,以平衡成本和性能的需求。另外,也要支持多元化的分布式索引技术,用于快速的数据检索。
在SQL查询引擎方面,需要定制查询优化器,支持分布式执行,适应更多类型的查询负载。
最后,也要选用一个合适的共享存储底座。
--
04 总结最后进行一下总结。
在前文中,首先介绍了物联网场景下的几类数据,包括元数据、消息、时序,时序是数据量最大的一类,架构设计部分也是以时序为例进行了场景分析。
其次,我们分析了物联网场景对存储产品的需求,我们也看到在很多场景下,存储成本和分析能力是主要需求。
从场景和需求出发,我们进行了架构设计选型的分析,并且得到了一定的结论。在架构方面,要选择云原生、存计分离、分层存储的架构。在存储引擎方面,要选择以列存为主,热数据行列混存的存储格式,同时支持元数据索引。在计算引擎方面,需要分布式的执行器和定制化的存储计算联合优化。同时,整个方案也需要充分利用云的弹性和云原生架构的优势。
最终我们希望通过这样的架构设计,在成本和性能方面相比传统方案有着一个数量级的优化,同时做到功能上的一站式和一体化。这样的架构优化也必然是一个持续的过程,最终持续助力物联网的数据增长和更丰富的场景应用的出现。
本文首发于微信公众号“DataFunTalk”。