使用说明
高可用
流式计算从架构上支持流的存算分离,在部署时要求系统中必须部署 snode,除数据读取外,所有流计算功能都只在 snode 上运行。
- snode 是负责运行流计算计算任务的节点,在一个集群中可以部署 1 或多个(至少 1 个),每个 dnode 中最多只能部署一个 snode,每个 snode 都有多个执行线程。
- snode 可以与其他节点(vnode/mnode)在相同的 dnode 上部署,但是从资源隔离的角度考虑,强烈推荐 snode 部署在单独的 dnode 上,这样可以保证资源隔离,流计算不会对写入、查询等业务造成太大干扰。
- 为了保证流计算的高可用,推荐在一个集群的多个物理节点中部署多个 snode:
- 流计算在多个 snode 间进行负载均衡。
- 每两个 snode 间互为副本,负责存储流的状态和进度等信息。
- 如果集群只部署了一个 snode,系统将不提供高可用保证。
部署 snode
创建流式计算之前,必须部署 snode,语法如下:
CREATE SNODE ON DNODE dnode_id;
查看 snode
用户可以通过 SHOW SNODES 查看 snode 相关信息。
SHOW SNODES;
若要展示更详细的信息,可以使用:
SELECT * FROM information_schema.`ins_snodes`;
删除 snode
删除 snode 时,需要确保 snode 及其副本同时在线,以便同步流的状态信息。当 snode 或其副本不在线时,删除会失败。
DROP SNODE ON DNODE dnode_id;
权限控制
流式计算的权限控制只与数据库的权限相关联,每个流计算可能与多个数据库相关,权限要求如下:
| 关联的数据库 | 数据库个数 | 鉴权行为 | 权限要求 |
|---|---|---|---|
| 流所属的数据库 | 1 个 | 创建、删除、停止、启动、手动重算 | 写入权限 |
| 触发表所属数据库 | 1 个 | 创建 | 读取权限 |
| 输出表所属数据库 | 1 个 | 创建 | 写入权限 |
| 计算数据源所属数据库 | 可能多个 | 创建 | 读取权限 |
重新计算
TDengine TSDB 的窗口类型大多与主键列相关联,比如事件窗口要根据按主键列排序后的数据进行窗口启动与关闭的计算。在使用窗口触发时,要求触发表的数据写入是尽可能有序的,这样才能保证流计算处理的效率是最高的。因此,一旦存在乱序写入的数据,这些数据将可能影响已经触发完成的窗口的计算结果正确性。同理,数据如果存在更新和删除的情况,也可能会影响计算结果的正确性。
支持使用 WATERMARK 来解决一定程度的乱序、更新、删除场景带来的问题。WATERMARK 是用户可以指定的基于事件时间的时长,它代表的是事件时间在流计算中的进展,体现了用户对于乱序数据的容忍程度。当前处理的最新事件时间 - WATERMARK 指定的固定间隔 即为当前水位线,只有写入数据的事件时间早于当前水位线才会进入触发判断,只有窗口或其他触发的时间条件早于当前水位线才会启动触发。WATERMARK 对于定时触发(PERIOD)不生效,定时触发模式下不会有重新计算。
对于超出 WATERMARK 的乱序、更新、删除场景,使用重新计算的方式来保证最终结果的正确性,重新计算意味着对于乱序、更新和删除的数据覆盖区间重新进行触发和运算。重算时输出表中已经产生的计算结果不会被删除,会重新写入新的结果,为保证这种方式的有效性,用户需要确保其计算语句和数据源表是与处理时间无关的,也就是说同一个触发即使执行多次其结果依然是有效的。
重新计算可以分为自动重新计算与手动重新计算,如果用户不需要自动重新计算,可以通过选项关闭。
手动重算
手动重新需要用户手动发起,在需要时可以通过 SQL 启动。
RECALCULATE STREAM [db_name.]stream_name FROM start_time [TO end_time];
说明:
- 可以根据需要来指定需要重算流的一段时间区间(事件时间)内的数据。如果未指定结束时间(end_time),重算区间将从指定的开始时间(start_time)一直到用户启动手动重算时刻流的当前计算进度截至。
- 不适用于定时触发(PERIOD),适用于其他所有触发类型。
- 计数窗口触发的手动重算必须同时指定开始时间与结束时间,只适用于当前流进度已经完成部分的时间区间的触发重算,如果指定的重算区间包含流当前还未启动计算的区间将自动忽略该重算请求。流计算会在该时间区间内重新划分触发窗口并进行重算,在这种情况下重新划分的窗口与重算前已经完成计算的窗口可能存在不对齐的情况,因此用户可能需要先手动删除结果表中重算区间内的结果,这样才能保证结果表中不会同时存在多次计算的结果。同理,如果未指定重算结束时间,该重算请求将自动被忽略。对于这种需要从某一时刻开始而没有结束时间的重算需求,可以通过先删流,再重建并指定
FILL_HISTORY_FIRST的方式来满足。
非典型数据写入场景
数据乱序
数据乱序指的是触发表的乱序写入行为,计算不关心数据源表是否乱序,但是用户需要从业务的角度确保在触发发生时数据源表的数据已经写入完成。根据触发方式的不同,数据乱序的影响和处理也不相同。
| 触发方式 | 影响和处理 |
|---|---|
| 定时触发 滑动触发 计数窗口触发(滑动步长不为 1) | 忽略,不处理 |
计数窗口触发(滑动步长为 1,例如 COUNT_WINDOW(1) 或 COUNT_WINDOW(n, 1)) | 默认处理:通过重算进行处理 可选处理:通过 STREAM_OPTIONS(IGNORE_DISORDER) 忽略,不处理 |
| 其他窗口触发 | 默认处理:通过重算进行处理 可选处理:忽略,不处理 |
数据更新
数据更新是指同一个时戳的数据被重复写入多次,其他列可以更新或不更新,数据更新操作也只针对触发表和触发操作有影响,对计算过程本身无影响。根据触发方式的不同,数据更新的影响和处理也不相同。 触发方式
| 触发方式 | 影响和处理 |
|---|---|
| 定时触发 滑动触发 计数窗口触发(滑动步长不为 1) | 忽略,不处理 |
计数窗口触发(滑动步长为 1,例如 COUNT_WINDOW(1) 或 COUNT_WINDOW(n, 1)) | 默认当做乱序数据处理(重算) 可选处理:通过 STREAM_OPTIONS(IGNORE_DISORDER) 忽略,不处理 |
| 其他窗口触发 | 当做乱序数据处理(重算) |
数据删除
数据删除也只针对触发表和触发操作有影响,对计算过程本身无影响。根据触发方式的不同,数据删除的影响和处理也不相同。
| 触发方式 | 影响和处理 |
|---|---|
| 定时触发 滑动触发 计数窗口触发(滑动步长不为 1) | 忽略,不处理 |
计数窗口触发(滑动步长为 1,例如 COUNT_WINDOW(1) 或 COUNT_WINDOW(n, 1)) | 默认处理:忽略,不处理 可选处理:通过 STREAM_OPTIONS(DELETE_RECALC) 当做乱序数据处理(重算) |
| 其他窗口触发 | 默认处理:忽略,不处理 可选处理:当做乱序数据处理(重算) |
过期数据
引入 expired_time 来设置数据的过期时间,流的触发产生的每个分组根据最新数据的事件时间和 expired_time 来判断新数据是否过期,过期数据的临界点通过最新事件时间减去 expired_time 得出,所有早于过期数据临界点的数据视为过期数据。
- 过期数据只针对触发表的实时数据,历史数据与其他表的数据没有过期数据的概念。过期数据的判断是在流触发时进行的,数据是否过期与其写入数据库的时机息息相关,所有按照事件时间顺序写入的数据都不会是过期数据,只有乱序写入的数据才可能是过期数据。
- 过期数据不会自动触发产生新的计算和重算,也就意味着在所有触发方式下,过期数据都将被忽略处理(不进行计算和重算)。如果用户没有需要忽略计算和重算的时间区间,则不需要指定
expired_time。如果用户指定了过期数据,同时想对部分过期数据进行计算或重算,可以通过手动重算的方式实现。 - 过期数据只对是否产生自动触发有影响,不对计算数据的范围有任何影响。因此如果某次触发的计算范围包含触发表中的过期数据,这部分过期数据仍然会被计算使用。
库表操作说明
流计算创建后,如果用户对每个流计算涉及的库表进行了操作,这些操作对流的影响和流对操作的处理总结如下:
| 操作 | 影响与流的处理 |
|---|---|
| 用户在触发超级表(非虚拟超级表)下新建子表并写入 | 新的子表自动加入当前流计算,可能加入某个分组或新产生一个分组 |
| 用户在触发虚拟超级表下新建子表并写入 | 忽略不额外处理 |
| 用户删除触发超级表的子表 | 默认忽略处理 某些触发方式可指定自动重算,可指定是否删除子表对应的结果表(只适用按子表分组的流) |
| 用户删除触发表 | 忽略不额外处理 |
| 用户在触发表上新增列 | 忽略不额外处理 |
| 用户删除触发表的列 | 忽略不额外处理 |
| 用户修改触发超级表的子表标签值 | 如果该标签列被流作为触发分组列使用则不允许操作,报错处理 否则忽略不处理 |
| 用户修改触发表的列 schema | 忽略不额外处理(读取时发现 schema 不一致报错) |
| 用户修改、删除数据源表 | 忽略不额外处理 |
| 用户修改、删除输出表 | 忽略不额外处理(写入时发现 schema 不一致报错,发现表不存在重新建表) |
| 用户拆分 vnode | 当被拆分 vnode 所在库为数据源库或触发表库时不允许 当存在虚拟表触发或虚拟表计算时不允许 用户在确认无影响后可指定强制执行( SPLIT VGROUP N FORCE) |
| 用户删除数据库 | 当被删库为某个流的数据源库、或触发表库且不是该流的所在库时不允许 当存在非目标数据库的虚拟表触发或虚拟表计算流时不允许 用户在确认无影响后可指定强制执行( DROP DATABASE name FORCE) |
除了上表中有明确限制和额外处理的操作外,其他未说明的操作和上表中说忽略不额外处理*的操作都没有限制。但是如果操作对流的计算可能产生影响,需要用户根据情况自行进行处理,可选忽略或者通过手动重算的方式进行重新计算。
配置参数说明
流计算相关配置参数包括,详细参见 taosd 参考手册
- numOfMnodeStreamMgmtThreads:mnode 流计算管理线程个数
- numOfStreamMgmtThreads:vnode/snode 流计算管理线程个数
- numOfVnodeStreamReaderThreads:vnode 流计算读线程个数
- numOfStreamTriggerThreads:流计算触发线程个数
- numOfStreamRunnerThreads:流计算执行线程个数
- streamBufferSize:流计算可以使用的最大缓存大小,只适用于
%%trows的结果缓存(单位:MB) - streamNotifyMessageSize:用于控制事件通知的消息大小
- streamNotifyFrameSize:用于控制事件通知消息发送时底层的帧大小
规则和限制
流式计算功能在使用上的一些规则和限制说明如下:
- 创建流计算前,集群中必须部署 snode,建流时必须存在可用(正常运行状态)snode。
- 每个流属于一个特定的数据库,因此建流前系统中必须已经存在数据库,同一个数据库中的流不允许重名。
- 流的触发表与数据源表可以相同,也可以不相同,可以跨库使用。
- 流的输出表可以与流、触发表、数据源表在不同的库中,不能与触发表或数据源表相同。
- 流的输出表(超级表和普通表)在建流时自动创建,如需写入到已经存在的表中,需要结构完全匹配。
- 每个分组的输出子表不需要提前创建,运算过程中输出结果时会自动创建。
- 每个触发分组的计算结果会写入到同一个子表中,没有指定触发分组时所有计算结果写入到同一个普通表中。
- 如果不同分组指定生成的子表名相同,那么不同分组的计算结果就会保存到同一个子表中,需要用户自行确认这是预期的行为,否则用户需要确保每个分组生成的子表名都是唯一的。
- 用户除了可以指定子表名外,也可以根据需要指定输出超级表的标签列以及每个子表的标签列的值。
- 流计算可以嵌套使用,也就是说可以基于一个流的输出表再创建一个新的流计算。
- 计数窗口触发不支持乱序、更新、删除的自动处理(采取忽略处理的方式),在非
FILL_HISTORY_FIRST模式下历史与实时窗口可能不对齐。 - 对于超级表的窗口触发方式,只有
interval和session窗口支持按照标签、子表分组和不分组,其他窗口只支持按子表分组。 - 不支持在查询中使用伪列,
qstart、qend、qduration。
短期使用限制
- 暂不支持按普通数据列分组的场景。
- 暂不支持
Geometry数据类型。 - 暂不支持在
NOTIFY_OPTIONS中使用ON_FAILURE_PAUSE选项。
兼容性说明
相比于 3.3.6.0 版本,流计算进行了全新设计。老版本升级之前要做如下动作后,在新的流计算版本上进行重建。
- 删除所有的流计算任务
- 删除所有的 TSMA
- 删除所有的 snode
- 删除 snode 相关目录
- 配置项
dataDir下的 snode 目录,默认值/var/lib/taos/snode - 原配置项
checkpointBackupDir指定的目录,默认值/var/lib/taos/backup/checkpoint/
- 配置项
- 删除所有的结果表
注意:如果未进行以上操作,taosd 会启动失败。








