TDengine在智慧排水系统中的应用介绍

2022-05-24 00:00:00 查询 数据 设备 采集 液位

业务场景

智慧排水系统中需要对排水设备中的液位进行监测。通常会在被监测区域部署电流液位传感器,采集电流液位频率。传感器采集的信息通过MQTT协议传到网关,网关收集到信息后会定时推送到业务后台服务,由服务层来做数据存储和实时分析。设备运行数据放在SQLServer里面,液位电流频率等不重要又特别多的数据放在Taos里面。

智慧排水系统整体处理流程

整个智慧排水系统包含数据采集层、数据传输层、数据平台层和业务处理层几个模块,具体的处理流程如下图所示:


在目前的应用场景中,海量的数据来自拦蓄盾检测设备上报的数据。在这些监测数据的处理流程上,数据从网关推送过来后会有一个判断是否实时数据。对于非实时数据,则会流经Redis去重,做报警判断然后写入SqlServer。对于实时数据则直接写入TDengine,不需要再经过Redis。之后前端需要的一些类似液位电流数据等就可以直接从TDengine访问。在这之前,所有数据都是使用SQLServer存储,发现数据量达到2000万后SQLServer的查询时延已经非常慢,不得不做分库分表操作来提高查询速度,但这个解决方法遇到跨库跨表的查询非常不便。

TDengine中的数据建模

TDengine是一个专门为物联网结构化数据流设计的时序数据库,其建库、建表的思路与关系库完全不同,遵循一个数据流隔离的原则。物联网设备产生的数据是按照时间顺序产生的数据流。在智慧排水系统,我们往往关心某一个液位计在一段时间范围内的变化趋势或大、小值这些统计量。


用关系型数据库比如SQLServer存储时序数据时,做法通常是所有同类设备的数据都进同一张表,每条记录会包含设备ID、数据采集(或入库)时间戳、采集到的值,并按照时间范围来分表提速。

这种做法的弊端在于查询麻烦且效率低。从关系型数据库中查询某一个设备的数据,就需要通过设备ID把其他设备的数据从大表中过滤掉,且每查询一个设备,就要面临过滤其他设备数据的开销。

TDengine的设计思路是一个数据源(设备)一个表,每个数据源按照时间顺序产生的消息流可以流入一个表中,不与其他数据流混合。表的主键是数据记录采集或入库的时间戳,其他字段是采集的值。

这样在TDengine中查询某个设备的指定时间段数据时,查询就简化为找到该设备的表并按照主键(时间戳)过滤搜索数据记录,效率大大提升。

此外,在TDengine中,我们为了方便管理设备的静态信息,也创建了超级表,并将设备ID和分组等作为标签定义好。

具体到我们的场景中,我们的建库、建表思路如下:

  • 数据库

    数据库创建主要依据业务模块来,把泵站、泵闸等上报数据分开存储。


             name              |     created time     |  ntables  |  vgroups  |replica| days  |  keep1,keep2,keep(D)   |  tables   |   rows    | cache(b)  |      ablocks       |tblocks| ctime(s)  | clog | comp |time precision|  status  |
==============================================================================================================================================================================================================================================
log | 19-09-06 10:36:33.888| 3| 1| 1| 10|30,30,30 | 32| 1024| 2048| 2.00000| 32| 3600| 1| 2|us |ready |
hgm | 19-09-08 22:42:58.873| 12| 1| 1| 10|3650,3650,3650 | 1000| 4096| 16384| 4.00000| 100| 3600| 1| 2|ms |ready |
jlj | 19-09-08 23:01:12.251| 17| 1| 1| 10|3650,3650,3650 | 1000| 4096| 16384| 4.00000| 100| 3600| 1| 2|ms |ready |
bengzhan | 19-09-08 23:01:21.895| 93| 1| 1| 10|3650,3650,3650 | 1000| 4096| 16384| 4.00000| 100| 3600| 1| 2|ms |ready |
bengzha | 19-09-08 23:01:29.272| 15| 1| 1| 10|3650,3650,3650 | 1000| 4096| 16384| 4.00000| 100| 3600| 1| 2|ms |ready |
|ready </font>

  • 超级表

    超级表的结构非常简单,采集字段就是时间戳ts和采集值val。但此处定义了两个标签,用于描述具体的点位静态信息。


taos> describe rtdata;
Field | Type | Length | Note |
=======================================================================================================
ts |TIMESTAMP | 8| |
val |FLOAT | 4| |
sncode |BINARY | 20|tag |
pointcode |BINARY | 10|tag |

taos> show stables;
name | created time |columns| tags | tables |
====================================================================================================================
rtdata | 19-09-09 18:15:42.243| 2| 2| 12|

  • 普通表


taos> show tables;
table_name | created time |columns| stable |
=================================================================================================================================================================
sch_8_n_level | 19-09-09 18:24:22.655| 2|rtdata |
sch_7_n_level | 19-09-09 18:24:22.620| 2|rtdata |
sch_6_n_level | 19-09-09 18:24:22.585| 2|rtdata |
sch_29_n_level | 19-10-30 11:35:01.292| 2|rtdata |
sch_5_n_level | 19-09-09 18:24:22.550| 2|rtdata |
sch_4_n_level | 19-09-09 18:24:22.514| 2|rtdata |
sch_30_n_level | 19-10-29 14:54:53.446| 2|rtdata |
sch_3_n_level | 19-09-09 18:24:22.479| 2|rtdata |
sch_2_n_level | 19-09-09 18:24:22.442| 2|rtdata |
sch_10_n_level | 19-09-09 18:24:25.338| 2|rtdata |
sch_1_n_level | 19-09-09 18:24:22.408| 2|rtdata |
sch_9_n_level | 19-09-09 18:24:22.691| 2|rtdata |


TDengine的优势


高写入速度

用下来感受是TDengine的数据写入性能非常高。现在的接入网关的设备数是23个液位9个频率计9个电流计。总共10个拦蓄盾、3个泵站。3个截留井。


1个泵闸,总共有40张表,每张表每天新增6万条数据,现在每张表的大约三百万条数据。使用TDengine带来的大好处是不用再考虑SQLServer中的分库分表操作,数据不断写入一个月后,查询时延也没有增加。


降采样查询

TDengine为监控设备数据分析提供了一个非常有用的功能 -- interval,即按照时间窗口进行降采样。比如在排水系统中,我们往往要计算拦蓄盾每隔20分钟液位值,这种分析可以简单由下面这个SQL语句实现。

select avg(val) from sch_3_n_level where ts > '2019-10-15 00:00:00' and ts < '2019-11-15 00:00:00' interval(20M);

新数据显示

在现在的监测系统中,需要大屏实时显示液位计的新读数。这里正好用上TDengine自带的缓存功能。TDengine为每张表在内存中分配了一定的缓存空间,来存储热的记录,实时查询效率非常高。查询语法用到了last和last_row。

select last_row(*) from rtdata group by sncode;

进而用VUE和hightopo的构建组态可视化界面,实时显示新液位数据。网关输出新液位,后端推送给前端,三维页面用hightopo展示液位。做出来的效果也是非常酷的。


低内存、高压缩比
在使用中,发现TDengine处理13个设备、百万量级的数据量的写入任务,内存开销只有1.5GB。查询时,内存增长觉察不出来。整体内存开销比SQLServer降低了50%。

在数据落盘后,查看/var/lib/taos下的数据文件大小,原来5GB的原始数据,经TDengine压缩后只有80MB,压缩比为1.6%。

未来的展望

整体来讲,TDengine对于处理高频采集的结构化时序数据吞吐量、资源开销和压缩都非常。但目前TDengine还不能像Redis那样做去重以及报警,这块后面也会尝试使用TDengine自带的流式计算和订阅来尝试实现报警,看能否进一步简化架构省掉Redis和SQLServer的工作。希望TDengine官方也能在这方面有更多支持,能越来越棒!

来源 https://www.modb.pro/db/168924

相关文章