一文学会如何使用 TDengine 3.0 中的流式计算

时间:2022-11-29 07:56:28

小 T 导读​​TDengine​​ 3.0 引入了全新的流式计算引擎,既支持时间驱动的流式计算,也支持事件驱动的流式计算。本文将对新的流式计算引擎的语法规则进行详细介绍,方便开发者及企业使用。

TDengine 是一款开源、云原生的​​时序数据库​​(​​Time Series Database​​,​​TSDB​​),专为物联网、工业互联网、金融、IT 运维监控等场景设计并优化。近期发布的 TDengine 3.0,全新的流式计算引擎是其一大亮点。

TDengine 3.0 的流式计算引擎提供了实时处理写入的数据流能力,使用 SQL 定义实时流变换,当数据被写入流的源表后,数据会被以定义的方式自动处理,并根据定义的触发模式向目的表推送结果。它提供了替代复杂流处理系统的轻量级解决方案,并能够在高吞吐的数据写入情况下,提供毫秒级的计算结果延迟。

流式计算可以包含数据过滤,标量函数计算(含 UDF),以及窗口聚合(支持滑动窗口、会话窗口与状态窗口),可以以超级表、子表、普通表为源表,写入到目的超级表。在创建流时,目的超级表将被自动创建,随后新插入的数据会被流定义的方式处理并写入其中,通过 partition by 子句,可以以表名或标签划分 partition,不同的 partition 将写入到目的超级表的不同子表。

TDengine 的流式计算能够支持分布在多个 vnode 中的超级表聚合;还能够处理乱序数据的写入:它提供了 watermark 机制以度量容忍数据乱序的程度,并提供了 ignore expired 配置项以决定乱序数据的处理策略——丢弃或者重新计算。
下面我们就一起看一下 TDengine 中流式计算相关的 SQL 语法。



流式计算的创建、删除与展示



创建

CREATE STREAM [IF NOT EXISTS] stream_name [stream_options] INTO stb_name AS subquery
stream_options: {
TRIGGER [AT_ONCE | WINDOW_CLOSE | MAX_DELAY time]
WATERMARK time
}

其中 subquery 是 select 普通查询语法的子集:

subquery: SELECT select_list
from_clause
[WHERE condition]
[PARTITION BY tag_list]
[window_clause]

支持会话窗口、状态窗口与滑动窗口,其中,会话窗口与状态窗口搭配超级表时必须与 partition by tbname 一起使用:

window_clause: {
SESSION(ts_col, tol_val)
| STATE_WINDOW(col)
| INTERVAL(interval_val [, interval_offset]) [SLIDING (sliding_val)]
}

在上述语句中,SESSION 是会话窗口,tol_val 是时间间隔的最大范围。在 tol_val 时间间隔范围内的数据都属于同一个窗口,如果有连续两条数据的时间超过 tol_val,则自动开启下一个窗口。窗口的定义与时序数据特色查询中的定义完全相同,详见 ​​TDengine 特色查询​​。

例如,使用如下语句创建流式计算,同时自动创建名为 avg_vol 的超级表,此流计算以一分钟为时间窗口、30 秒为前向增量统计这些电表的平均电压,并将来自 meters 表的数据的计算结果写入 avg_vol 表,不同 partition 的数据会分别创建子表并写入不同子表。

CREATE STREAM avg_vol_s INTO avg_vol AS
SELECT _wstartts, count(*), avg(voltage) FROM meters PARTITION BY tbname INTERVAL(1m) SLIDING(30s);



删除

DROP STREAM [IF NOT EXISTS] stream_name;

仅删除流式计算任务,由流式计算写入的数据不会被删除。



展示

SHOW STREAMS;

若要展示更详细的信息,可以使用:

SELECT * from performance_schema.`perf_streams`;



流式计算的 partition

我们可以使用 PARTITION BY TBNAME 或 PARTITION BY tag 对一个流进行多分区的计算,每个分区的时间线与时间窗口是独立的,会各自聚合,并写入到目的表中的不同子表。如果不带 PARTITION BY 选项,那所有的数据将写入到一张子表。

流式计算创建的超级表有唯一的 tag 列 groupId,每个 partition 会被分配唯一 groupId。与 schemaless 写入一致,我们通过 MD5 计算子表名,并自动创建它。



流式计算的触发模式

在创建流时,可以通过 TRIGGER 指令指定流式计算的触发模式。

对于非窗口计算,流式计算的触发是实时的;对于窗口计算,目前提供如下 3 种触发模式:

  1. AT_ONCE:写入立即触发
  2. WINDOW_CLOSE:窗口关闭时触发(窗口关闭由事件时间决定,可配合 watermark 使用)
  3. MAX_DELAY time:若窗口关闭,则触发计算。若窗口未关闭,且未关闭时长超过 max delay 指定的时间,则触发计算。

由于窗口关闭是由事件时间所决定的,如果因事件流中断、或持续延迟导致事件时间无法更新,可能无法得到最新的计算结果。因此,流式计算提供了以事件时间结合处理时间计算的 MAX_DELAY 触发模式,MAX_DELAY 模式在窗口关闭时会立即触发计算。此外,当数据写入后,计算触发的时间超过 max delay 指定的时间,则立即触发计算。



流式计算的窗口关闭

流式计算以事件时间(插入记录中的时间戳主键)为基准计算窗口关闭,而非以 TDengine 服务器的时间,这样可以避免客户端与服务器时间不一致带来的问题,有效解决乱序数据写入等难题。同时,流式计算还提供了 watermark 来定义容忍的乱序程度。
在创建流时,我们可以在 stream_option 中指定 watermark,它定义了数据乱序的容忍上界。流式计算通过 watermark 来度量对乱序数据的容忍程度,watermark 默认为 0。

T = 最新事件时间 – watermark

每次写入的数据都会以上述公式更新窗口关闭时间,并将窗口结束时间 < T 的所有打开的窗口关闭,若触发模式为 WINDOW_CLOSE 或 MAX_DELAY,则推送窗口聚合结果。


一文学会如何使用 TDengine 3.0 中的流式计算