使用 SeaTunnel 玩转 IoTDB 数据同步 | 讲座回顾

前言

在今年 10 月份 Apache IoTDB & SeaTunnel 联合 meetup 上,SeaTunnel Committer 的王海林带来题为《使用 SeaTunnel 玩转 IoTDB 数据同步》的主题演讲,详细阐述了 IoTDB 支持接入 SeaTunnel 的实现过程,让用户更深刻地理解 IoTDB 数据同步的操作方法和原理。本文根据此演讲修改整理而成。

本篇首先介绍 Apache IoTDB 和 SeaTunnel 的基本概念,并在此基础上着重介绍一下 IoTDB Connector 的功能特性,随后会深入分析一下 IoTDB Connector 的数据读取和数据写入功能以及实现的解析,最后会展示一些典型的使用场景和案例,让大家了解如何使用 IoTDB Connector 落地到生产环境。

1

Apache IoTDB 

& SeaTunnel 

基本概念介绍

Apache IoTDB 是一款工业物联网时序数据库管理系统,可一体化收集、存储、管理与分析物联网时序数据,满足工业物联网领域的海量数据存储、高速数据读取和复杂数据分析需求。IoTDB 的架构如下图所示,分为三个部分:时序文件、数据库引擎和分析引擎。

时序文件部分里,TsFile 是 IoTDB 自研的一种专门为时序数据设计的文件存储格式,支持高效的压缩和查询性能,能够为上层应用提供出色的数据存储和查询支持。将时序数据存储至 TsFile 后,即使用TsFile 格式进入 IoTDB 数据管理引擎,在此阶段既可使用交互工具进行查询和预处理,也可通过可视化平台进行可视化操作。分析引擎作为可选的分析组件,可以进一步提供数据的导入导出、数据分析、异常监测等功能,也可与其他大数据系统无缝集成。

使用 SeaTunnel 玩转 IoTDB 数据同步 | 讲座回顾_第1张图片

SeaTunnel 是一个分布式、高性能、易扩展、用于海量数据(离线&实时)同步和转化的数据集成平台。下图架构图可见,为了从各式各样的数据源读取数据并写入到各式各样的数据源,SeaTunnel 做了一套抽象的 API。基于这些API,SeaTunnel 会有一个 translation 层把这些 API 翻译到对应的执行引擎上。数据同步依赖 Connector 连接器读取和写入数据,连接器由 Source 和 Sink 构成。Source 负责从各种数据源中读取数据,将其转化成 SeaTunnelRow 抽象层(匹配 SeaTunnel 定义的数据类型),Sink 负责从抽象层上拉取数据,写到具体的数据存储上,转化成存储具体的格式。

使用 SeaTunnel 玩转 IoTDB 数据同步 | 讲座回顾_第2张图片

使用 SeaTunnel 玩转 IoTDB 数据同步 | 讲座回顾_第3张图片

2

Apache IoTDB Connector 

功能特性

首先介绍下集成 SeaTunnel 的 Apache IoTDB Connector 到底支持哪些功能,为大家提供参考。

2.1

Source 功能特性

使用 SeaTunnel 玩转 IoTDB 数据同步 | 讲座回顾_第4张图片

首先是 IoTDB 支持 Source 的典型的使用场景,如上图所示,IoTDB支持如批量读取 device、字段投影、数据类型映射、并行读取等。

IoTDB 有一个类似于 group by device 的 SQL 语法,可以把多个设备的数据统一进行批次读取。基本的数据类型投影时,在IoTDB 的 SQL 查询任何指标时会默认带上 time,或 group by device 会带上device 列,SeaTunnel 也默认支持投影到 SeaTunnel 的列上。

关于并行读取,IoTDB 数据中自带时间戳,可用时间戳划分范围来实现并行读取。

状态的恢复,因为 SeaTunnel 对读取的时间范围划分了不同的 split,所以 IoTDB 可以根据 split 位置信息进行恢复。

2.2

Sink 功能特性

使用 SeaTunnel 玩转 IoTDB 数据同步 | 讲座回顾_第5张图片

IoTDB 支持 Sink 的典型的使用场景,如上图所示。关于元数据提取,IoTDB 支持从 SeaTunnelRow 中提取 measurement、device 等元数据,支持从  SeaTunnelRow 中提取或使用当前处理时间。批量提交、异常重试也是支持的。

3

Apache IoTDB 数据读取解析

接下来解析一下 IoTDB 在 SeaTunnel 上实现的数据读取功能解析。

3.1

数据类型映射

首先是数据类型映射,实际上是把 IoTDB 的数据类型读到 SeaTunnel 上,所以要转化成 SeaTunnel 的数据类型。

使用 SeaTunnel 玩转 IoTDB 数据同步 | 讲座回顾_第6张图片

这里列出来的 IoTDB 的数据类型,BOOLEAN、INT32、INT64 等都有对应的 SeaTunnel 数据类型,所以都可互相转化。其中 IoTDB 的 INT32 类型是可以根据 SeaTunnel 上的读取类型进行映射的,当值的范围比较小时,也可以映射成TINYINT、SMALLINT或 INT。

下图为对应的示例代码,展示类型转换的地方如何做映射。

使用 SeaTunnel 玩转 IoTDB 数据同步 | 讲座回顾_第7张图片

3.2

字段投影

读取时的字段投影,我们在读 IoTDB 数据时,可以自动映射 Time 字段,也可以选择部分数据映射到 SeaTunnel 上,比如TIMESTAMP、BIGINT。

通过 IoTDB 的 SQL提取列码,可以只提取部分需要的列,在 SeaTunnel 上使用时,可以通过 feilds 来指定列映射到 SeaTunnel 后的名字、类型等。最后读取到SeaTunnel上的数据结果如下图所示。

使用 SeaTunnel 玩转 IoTDB 数据同步 | 讲座回顾_第8张图片

上面大家其实看到了,我们 SQL 里面没有查 time 这个列,但实际查出结果是有这个列的,所以 IoTDB 的 time 列的字段也可以在 SeaTunnel 上进行投影,time 列实际上可以投影成不同的数据类型,用户可以根据自己的需要来进行转换。下图为实现逻辑。

使用 SeaTunnel 玩转 IoTDB 数据同步 | 讲座回顾_第9张图片

3.3

批量读取 device

读取还涉及到批量读取 device。这是一个常见的需求,因为我们同步数据的时候可能都是大批量地做同数据结构的数据同步。

IoTDB 中的 align by device 语法 SeaTunnel 也可用,这样就可以把 device列也投影到 SeaTunnelRow 上,如下图所示。

使用 SeaTunnel 玩转 IoTDB 数据同步 | 讲座回顾_第10张图片

假设  IoTDB 中有一张表,我们通过语法把  device 列也做成数据,投影到 SeaTunnel 上,配置了device name 列并指定数据类型之后,我们最终读到 SeaTunnel 上的数据格式如下图所示,包含time、device列,以及实际的数据值。这样可以做到批量读取相同的device的数据。

使用 SeaTunnel 玩转 IoTDB 数据同步 | 讲座回顾_第11张图片

3.4

并行读取

如果要并行读取,我们可能要对这张表的数据范围通过 IoTDB 中的 time 列进行范围划分,让并行的线程/进程读取特定范围的数据。按照 time 范围划分,SeaTunnel 需设置三个配置,lower_bound、upper_bound 和 num_partitions。通过配置三个参数,最终效果就会是据此转化成查询的 SQL,原始的 SQL 会加上查询条件,划分成不同的 split 达成实际的读取的 SQL。

split 分好了,下一步就是要分给每一个并行的 reader, 需要遵循一个分配逻辑。这个逻辑就是根据 split 中的 ID 向 reader 取模,这个可能有较大的随机性,如果 split 的 ID 比较散列的话就会比较均匀,要根据 Connector 的具体情况实现。

使用 SeaTunnel 玩转 IoTDB 数据同步 | 讲座回顾_第12张图片

实现的效果如下图所示。

使用 SeaTunnel 玩转 IoTDB 数据同步 | 讲座回顾_第13张图片

3.5

状态恢复

在读取的时候还会涉及到状态恢复,因为如果任务比较大,读取的时间会较长,中间如果出现错误或者异常,就要考虑如何从出错的点恢复状态,恢复之后接着再读。SeaTunnel 的状态恢复主要是通过 reader 把 未读取的 split 信息存到 state里,而后引擎在读取时会定期对 state 做快照保留,恢复的时候就可以恢复最后一次快照,恢复后继续读取。

使用 SeaTunnel 玩转 IoTDB 数据同步 | 讲座回顾_第14张图片

使用 SeaTunnel 玩转 IoTDB 数据同步 | 讲座回顾_第15张图片

使用 SeaTunnel 玩转 IoTDB 数据同步 | 讲座回顾_第16张图片

4

IoTDB Connector 

数据写入解析

接下来是关于 IoTDB 在 SeaTunnel 上实现的数据写入功能解析。

4.1

数据类型映射

数据写入也涉及到数据类型映射,但这里与数据读取相反,是把 SeaTunnel 的数据类型转换为IoTDB 类型。IoTDB 的 INT32 在写入过程会涉及到 TINYINT 和 SMALLINT 的数据类型提升,其他数据类型均可一对一转换。

使用 SeaTunnel 玩转 IoTDB 数据同步 | 讲座回顾_第17张图片

下图为对应的代码,实现逻辑需要看我们具体的映射。

使用 SeaTunnel 玩转 IoTDB 数据同步 | 讲座回顾_第18张图片

4.2

元数据动态注入

在写入这块也有原数据的注入的问题,SeaTunnel 支持元数据的动态注入。当异构数据源写入 IoTDB 时,支持从每一行数据中提取 device、measurement、time,方法是通过序列化 SeaTunnelRow 时按配置提取固定列值。或者使用系统时间作为 time,如果未指定 time 列则填充当前系统时间;同时,还支持配置 storage group,自动附加到 device 前缀。

使用 SeaTunnel 玩转 IoTDB 数据同步 | 讲座回顾_第19张图片

举例来说,假设在 SeaTunnel 读取上图所示的数据格式的 row 的结构,可以通过配置同步到 IoTDB 中,获得的结果如下:

使用 SeaTunnel 玩转 IoTDB 数据同步 | 讲座回顾_第20张图片

提取了我们需要的温度、湿度这两个列,并提取了 ts 和device name来作为 IoTDB 的原数据。

4.3

批量提交与异常重试

另外,Sink 在写入时需要做处理批量和重试。对于批量,可以配置相应的批量配置,包括支持配置批量提交的条数与间隔;如果数据缓存到内存,可以开启独立线程定时提交。对于重试,SeaTunnel 支持配置重试次数,等待间隔与最大重试次数,以及当重试结束后,如果遇到不可恢复的错误也可以结束。

使用 SeaTunnel 玩转 IoTDB 数据同步 | 讲座回顾_第21张图片

5

IoTDB Connector 

数据写入解析

经过前面对读取数据和写入数据的解析之后,我们来看三个典型的使用场景示例。

5.1

从 IoTDB 导出数据

第一个场景是从 IoTDB 导出数据,这里举的例子是从 IoTDB 并行读取数据导到 Console 上。并行度为2,批次数为24,时间范围为 2022-09-25 ~ 2022-09-26。

我们假设在 IoTDB 有一张数据表,我们要把数据导到 Console 上,整个配置如下图所示,需要映射我们要导出的数据列以及查的时间范围。这是一个最简单的示例,实际使用中可能 Sink 端更为复杂,需要参考对应数据源的文档做相应的配置。

使用 SeaTunnel 玩转 IoTDB 数据同步 | 讲座回顾_第22张图片

5.2

导入数据到 IoTDB

另外一个典型的使用场景是把其他数据源的数据批量写入到 IoTDB。假设有一个外部的数据库表,有 ts、温度、湿度等列,我们将其导入到 IoTDB 中,要求有温度和湿度这两列,其他的可以不要。整个配置如下图所示,大家可以参考。这个例子批量写入频次为每 1024 条或每 1000 ms 提交一次,提取元数据为 device、timestamp,measurement。

使用 SeaTunnel 玩转 IoTDB 数据同步 | 讲座回顾_第23张图片

在 Sink 端主要是要指定 device 列的 key,比如从哪些数据中提取 device、时间是从哪一个类提取、要写哪些列到 IoTDB 等。可以看到,我们可以配置  storage group,也就是 IoTDB 的存储组,可以通过storage group 指定存储组。这个例子指定存储组为 root.test_group。

5.3

IoTDB 之间同步数据

第三个使用场景是在 IoTDB 与 IoTDB 之间同步数据,批量写入到 IoTDB。假设 IoTDB 中有一张表需要同步到另一个 IoTDB,同步过去之后存储组发生了变更,数据列的指标的名字也发生了变更,这时可以使用投影改写指标名称,并使用 SQL 改写存储组。

使用 SeaTunnel 玩转 IoTDB 数据同步 | 讲座回顾_第24张图片

使用 SeaTunnel 玩转 IoTDB 数据同步 | 讲座回顾_第25张图片

你可能感兴趣的:(iotdb,apache,数据库,java,大数据)