掘金 后端 ( ) • 2024-04-29 09:57

概述

物联网存在海量的设备、传感器,时序数据处理,传统数据库的解决方案很难满足海量数据的传输、解析、存储和实时的故障诊断分析。

1. 什么是时序数据?

时序数据是随时间不断产生的一系列数据,简单来说,就是带时间戳的数据。时序数据库 (Time Series Database,TSDB) 是优化用于摄取、处理和存储时间戳数据的数据库。此类数据可能包括来自服务器和应用程序的指标、来自物联网传感器的读数、网站或应用程序上的用户交互或金融市场上的交易活动。

其主要数据属性如下:

  • 每个数据点都包含用于索引、聚合和采样的时间戳。该数据也可以是多维的和相关的;
  • 写多读少,需要支持秒级和毫秒级甚至纳秒级高频写入;查询通常是多维聚合查询,对查询的延迟要求比较高
  • 数据的汇总视图(例如,下采样或聚合视图、趋势线)可能比单个数据点提供更多的洞察力。例如,考虑到网络不可靠性或传感器读数异常,我们可能会在一段时间内的某个平均值超过阈值时设置警报,而不是在单个数据点上这样做;
  • 分析数据通常需要在一段时间内访问它(例如,给我过去一周的点击率数据);

虽然其他数据库也可以在数据规模较小时一定程度上处理时间序列数据,但 TSDB可以更有效地处理随时间推移的数据摄取、压缩和聚合。简而言之,时序数据库是专门用于存储和处理时间序列数据的数据库,支持时序数据高效读写、高压缩存储、插值和聚合等功能。

2. 时序数据库概念

时序数据库是专门处理时序数据的数据库,因此其相关概念是和时序数据紧密联系的,下面是时序数据库的一些基本概念。

  • 度量 Metric:Metric 类似关系型数据库里的表(Table),代表一系列同类时序数据的集合,例如为空气质量传感器建立一个 Table,存储所有传感器的监测数据。
  • 标签 Tag:Tag 描述数据源的特征,通常不随时间变化,例如传感器设备,包含设备 DeviceId、设备所在的 Region 等 Tag 信息,数据库内部会自动为 Tag 建立索引,支持根据 Tag 来进行多维检索查询;Tag 由 Tag Key、Tag Value 组成,两者均为 String 类型。
  • 时间戳 Timestamp:Timestamp代表数据产生的时间点,可以写入时指定,也可由系统自动生成;
  • 量测值 Field:Field描述数据源的量测指标,通常随着时间不断变化,例如传感器设备包含温度、湿度等Field;
  • 数据点Data Point: 数据源在某个时间产生的某个量测指标值(Field Value)称为一个数据点,数据库查询、写入时按数据点数来作为统计指标;
  • 时间线 Time Series :数据源的某一个指标随时间变化,形成时间线,Metric + Tags + Field 组合确定一条时间线;针对时序数据的计算包括降采样、聚合(sum、count、max、min等)、插值等都基于时间线维度进行;

时序数据库的趋势

时序数据库的发展趋势,可以从DB-engines(Knowledge Base of Relational and NoSQL Database Management Systems)获取获取到,下图是DB-engines收录的数据库近24个月的发展趋势,其中时序数据库的活跃度最高,且随时间呈现越来越活跃的趋势。

image.png

3. 海量数据处理的挑战?

物联网存在海量的设备、传感器,时序数据处理的传统方案有如下问题:

  • 数据入库慢:单机写入吞吐量低,很难满足时序数据上千万级的写入压力;
  • 存储成本大:在对时序数据进行压缩时性能不佳,需占用大量机器资源;
  • 维护成本高:单机系统,需要在上层人工进行分库分表,维护成本高;
  • 非云原生:不支持分布式,对部署的平台有限制,没有好的扩展性、韧性、可观测性;
  • 查询性能差:海量实时数据的聚合分析性能差。
  • 数据孤岛:边云协同能力差。

IoT海量数据分析面临的问题.png

传统的解决方案都是用MySQL数据,在这种物联网传感器海量数据面前,这种关系型数据库很难满足需求。分库分表如何满足10几万台设备消息的故障分析、诊断和运维。

4. 常见的物联网架构

基于时序数据库搭建的高效的数据处理分析解决方案。

image.png

5. 实战案例

基于EMQX + TDEngine + Grafana实现时序数据可视化。当然这个只是简单的demo,企业级别的应用有更复杂的场景需求需要定制化开发。

image.png

1. EMQX部署

参考官方文档 https://www.emqx.io/docs/zh/latest/deploy/install-docker.html

2. TDEngine部署

## 拉取最新版本的镜像
docker pull tdengine/tdengine:latest

docker run -d -v ~/data/taos/dnode/data:/var/lib/taos \
  -v ~/data/taos/dnode/log:/var/log/taos \
  -p 6030:6030 -p 6041:6041 -p 6043-6049:6043-6049 -p 6043-6049:6043-6049/udp tdengine/tdengine

docker ps

docker exec -it 830fa78e7029 bash

#测试TDEngine写入性能
#默认的测试工具:taosBenchmark

SELECT COUNT(*) FROM test.meters;

SELECT AVG(current), MAX(voltage), MIN(phase) FROM test.meters;

SELECT COUNT(*) FROM test.meters WHERE location = "California.SanFrancisco";

SELECT AVG(current), MAX(voltage), MIN(phase) FROM test.meters WHERE groupId = 10;

SELECT FIRST(ts), AVG(current), MAX(voltage), MIN(phase) FROM test.d10 INTERVAL(10s);

3、安装Grafana

docker pull grafana/grafana
mkdir -p /data/grafana/{data,plugins,config}
chmod -R 777 /data/grafana/data
chmod -R 777 /data/grafana/plugins
chmod -R 777 /data/grafana/config

# 先临时启动一个容器
docker run --name grafana-tmp -d -p 3000:3000 grafana/grafana
# 将容器中默认的配置文件拷贝到宿主机上
docker cp grafana:/etc/grafana/grafana.ini /data/grafana/config/grafana.ini
# 移除临时容器
docker stop grafana-tmp
docker rm grafana-tmp

# 修改配置文件(需要的话)
vim /data/grafana/config/grafana.ini



# 启动 grafana
# 环境变量GF_SECURITY_ADMIN_PASSWORD:指定admin的密码
# 环境变量GF_INSTALL_PLUGINS:指定启动时需要安装得插件
#         grafana-clock-panel代表时间插件
#         grafana-simple-json-datasource代表json数据源插件
#         grafana-piechart-panel代表饼图插件

docker run -d \
    -p 3000:3000 \
    --name=grafana \
    -v /etc/localtime:/etc/localtime:ro \
    -v /data/grafana/data:/var/lib/grafana \
    -v /data/grafana/plugins/:/var/lib/grafana/plugins \
    -v /data/grafana/config/grafana.ini:/etc/grafana/grafana.ini \
    -e "GF_SECURITY_ADMIN_PASSWORD=admin" \
    grafana/grafana:10.2.2

注意: 安装报错,下面的报错是tdengine插件安装不是,直接去官网下载然后解压到挂载的插件目录即可。

root@dell:~# docker logs e4be980b813c
Error: ✗ failed to download plugin archive: Get "https://storage.googleapis.com/plugins-community/tdengine-datasource/release/3.5.0/tdengine-datasourread tcp 172.17.0.9:50750->142.251.43.27:443: read: connection reset by peer

4、测试验证

1、创建TDEngine 数据库和表结构

#  创建power数据库和d1001,主要统计一个地区连续的温度和湿度,并以趋势图展示。
CREATE DATABASE power;
#  切换数据库
USE power;  
# 创建超级表
CREATE TABLE sensor (ts timestamp, temp float, humi float) TAGS (location binary(64), groupdId int);
# 创建表
CREATE TABLE d1001 USING sensor TAGS ("Beijing.Chaoyang", 2);

insert into d1001 values (now,12.01,34);

2、创建EMQX webhook

1、webhook配置, 获取webhoos 的token配置

root@dell:~# curl 192.168.100.122:6041/rest/login/root/taosdata
{"code":0,"desc":"/KfeAzX/f9na8qdtNZmtONryp201ma04bEl8LcvLUd7a8qdtNZmtONryp201ma04"}
root@dell:~# curl -H 'Authorization: Taosd /KfeAzX/f9na8qdtNZmtONryp201ma04bEl8LcvLUd7a8qdtNZmtONryp201ma04' -d 'select * from power.d1001' 192.168.100.122:6041/rest/sql

root@dell:~# curl -H 'Authorization: Taosd /KfeAzX/f9na8qdtNZmtONryp201ma04bEl8LcvLUd7a8qdtNZmtONryp201ma04' -d 'select * from power.d1001' 192.168.100.122:6041/rest/sql
{"code":0,"column_meta":[["ts","TIMESTAMP",8],["temp","FLOAT",4],["humi","FLOAT",4]],"data":[["2024-04-16T05:33:49.444Z",12.01,34],["2024-04-16T05:40:47.885Z",12.01,34],["2024-04-16T05:40:52.693Z",12.02,34],["2024-04-16T05:40:55.923Z",12.03,34],["2024-04-16T05:40:58.572Z",12.03,34],["2024-04-16T05:41:02.294Z",12.03,32],["2024-04-16T05:41:05.907Z",12.04,32],["2024-04-16T05:41:10.118Z",12.05,32],["2024-04-16T05:41:15.019Z",12.08,32],["2024-04-16T05:41:48.098Z",12.07,32],["2024-04-16T05:41:54.716Z",12.06,32],["2024-04-16T05:41:57.598Z",12.06,32],["2024-04-16T05:42:00.284Z",12.06,32],["2024-04-16T05:42:01.945Z",12.06,32],["2024-04-16T05:42:06.562Z",12.07,32],["2024-04-16T05:42:09.188Z",12.07,32],["2024-04-16T05:42:11.995Z",12.07,32],["2024-04-16T05:42:13.553Z",12.07,32],["2024-04-16T05:42:14.874Z",12.07,32],["2024-04-16T05:42:16.152Z",12.07,32],["2024-04-16T05:42:19.663Z",12.06,32],["2024-04-16T05:42:21.119Z",12.06,32],["2024-04-16T05:42:24.345Z",12.06,32],["2024-04-16T05:42:25.717Z",12.06,32],["2024-04-16T05:42:27.777Z",12.06,32],["2024-04-16T05:42:44.065Z",12.06,32],["2024-04-16T05:42:48.591Z",12.06,32],["2024-04-16T05:42:50.818Z",12.06,32],["2024-04-16T05:42:52.611Z",12.06,32],["2024-04-16T05:42:54.918Z",12.06,32],["2024-04-16T05:42:57.069Z",12.06,32],["2024-04-16T05:42:58.599Z",12.06,32],["2024-04-16T05:43:00.444Z",12.06,32],["2024-04-16T05:43:09.248Z",12.06,32],["2024-04-16T05:43:13.334Z",12.06,32],["2024-04-16T05:43:15.691Z",12.06,32],["2024-04-16T05:43:16.933Z",12.06,32]],"rows":37}
 
2、topic 规则引擎配置
SELECT
  payload
FROM
  "sensor/data"

3、配置响应入库
insert into power.d1001 values(now, ${payload.temp}, ${payload.humi})

image.png

image.png

image.png

3、配置grafana可视化

1、配置DashBoard

  数据源配置TDEngine: 
  select ts,temp from power.d1001 where ts >= $from and ts < $to


image.png

参考

1、EMQX 官网(https://www.emqx.io/zh )
2、TDEngine 官网
3、Grafana 官网
4、基于时序数据库TDEngine的解决方案
5、阿里云物联网平台架构
6、DB-Engines Ranking of Time Series DBMS