作者:必和必拓研发部
小 T 导读:湖南必和必拓科技倒退有限公司定位于智慧城市建设与行业信息化,以后聚焦智慧住建、智慧环保、智慧司法以及智能制作四大畛域,既蕴含各类电子产品装置施工及维保,也包含自有软件研发及部署。
随着业务规模的逐步扩充,传统数据库越来越难以满足某些业务场景对查问、剖析、统计的进一步需要。为了突破当下困局,湖南必和必拓想到了三种解决方案,在进行了谨严的剖析后,咱们决定采纳物联网数据库,通过选型比照,时序数据库 TDengine 成为其首选计划。
如何在 TDengine 上进行数据建模、集群搭建、告警模块搭建?如何将数据更平滑地迁徙到 TDengine?在这些操作中,可能会遇到什么问题?又该如何解决?从湖南必和必拓的实践经验登程,本文将从代码层面一一解答。
业务场景及痛点
在一些业务场景中,咱们须要将长沙市在建工地的扬尘数据 (温度、湿度、pm2.5、pm10、pm100、噪声、风向、风速) 存储在数据库中,以便为业务提供查问、剖析和统计的操作。
但近来呈现了一个难题,咱们共有监测点 107 个,每分钟上送 1 条数据,每年就预计有“1076024*365 = 56,239,200”条数据,也就是 5600 多万条。目前已存储两年的数据,数据量总计约 1 亿多条。这些数据始终都被存储在 MySQL 数据库中,宏大的数据量使得查问速度越发迟缓,甚至局部页面呈现超时问题。
解决方案 1:MySQL 数据库分库分表
如果咱们将数据库扩散到不同的表上,单表的索引大小就失去了管制,对索引以及表构造的变更会变得更加不便和高效。当数据库实例的吞吐量达到性能的瓶颈时,咱们须要扩大数据库实例,让每个数据库实例承当其中一部分数据库的申请,合成总体的大申请量的压力。
弊病:
- 分库分表须要提前对数据做好布局。如果依照工夫对表进行程度划分,随着监控点减少,前面的表数据量可能越来越大,容易呈现数据热点问题;如果依照监测点 hash 取模对表进行程度划分,当监测点减少,进行扩大就会比拟艰难。例如:之前是 mod4,前面是 mod6,则须要对之前的历史数据从新进行解决。
- 在对数据进行统计分析时,可能须要进行多表的聚合查问,查问速度会受到影响。
解决方案 2:应用华为云物联网平台
华为云物联网基于物联网资产模型,整合物联网数据集成、荡涤、存储、剖析、可视化,为物联网数据开发者提供一站式服务,可能无效升高开发门槛,缩短开发周期,疾速实现物联网数据价值变现。
弊病:后期需设施厂商针对平台接口进行适配,接入当前零代码的形式的确在配置上会比拟不便,然而平台的费用以及实时流式计算按次免费的形式,整体费用过高。
解决方案 3:应用物联网数据库
- InfluxDB:高性能的时序数据库,能够高效的存储和查问时序数据。惋惜的是,目前社区版集群性能不开源。
- TDengine:TDengine 是一个简略快捷、高性能的时序数据库,提供高性能的同时也极大升高了装置、部署和保护的老本。
利用之后,TDengine 能解决之前令咱们较为头疼的一些问题,包含前文中形容的问题,它有以下 5 点次要劣势:
- 安装简单。下载 rpm 包,一个命令装置结束即可运行。
- 数据库开源,反对集群。
- 充分考虑时序数据的特点,以超级表为模型,将每个监测点的数据独自存储在一张表中,进步了插入和查问速度。
- 有丰盛的函数,反对窗口查问和间断查问。
- 自带 TDengineAlert 模块,和 AlertManager 联结应用,能够推送告警信息
综合思考以上解决办法,咱们发现,应用 TDengine 后,硬件老本和开发保护老本大大降低,写入和查问速度比 OpenTSDB 等还要高出一个级别。于是,TDengine 成为了咱们的首选解决方案。
接下来,我将把咱们在摸索 TDengine 时的一些重要操作、问题点以及解决办法等教训传递给大家。
对于 TDengine 装置
官网下载安装包,文中应用的是 2.0.20.12,即:TDengine-server-2.0.20.12-Linux-x64.tar.gz。安装包中蕴含装置命令, 解压后间接应用即可。
[root@hnbhbt ~]# tar -zxvf TDengine-server-2.0.20.12-Linux-x64.tar.gz
[root@hnbhbt ~]# cd TDengine-server-2.0.20.12
[root@hnbhbt ~]# ./install.sh
1. 启动 TDengine
[root@hnbhbt ~]# systemctl start taosd
2. 查看 TDengine 状态
[root@hnbhbt ~]# systemctl status taosd
3. 输出以下命令进入 TDengine 命令行
taos
呈现如下显示后示意进入胜利
Welcome to the TDengine shell from Linux, Client Version:2.0.20.12
Copyright (c) 2020 by TAOS Data, Inc. All rights reserved.
taos>
卸载: 须要手动删除配置文件以及日志
[root@hnbhbt ~]# sudo rm -rf /var/log/taos/
[root@hnbhbt ~]# sudo rm -rf /var/lib/taos/
[root@hnbhbt ~]# sudo rm -rf /etc/taos/taos.cfg
注: 装置过程中须要配置 TDengine 的 FQDN 为 hostname,通过 Linux 命令能够查看以后机器的 hostname,配置相应内容即可,官网倡议尽量不要应用 localhost,文中配置的是 hnbhbt.com
数据建模
表设计
-- 创立数据库
create database db_transfer_platform keep 730 replica 3;
-- 应用数据库
use db_transfer_platform;
-- 创立超表
create stable if not exists s_dust_history_data(ts timestamp,measured_value double,id int)tags(device_code nchar(30),channel_number nchar(30),signal_code nchar(30),status bool);
-- 删除超表
drop stable if exists s_dust_history_data;
-- ts 工夫戳;measured_value 测量值;id 平台主键;device_code 设施编号;channel_number 通道序号;signal_code 信号编号;status 在线状态
注:ts 默认为主键,不能为空;列名防止取要害值,否则无奈插入
数据插入
-- example: 创立子表,插入数据,查问数据
-- 子表名称[监测信号_设施编号] eg pm_25_1003055 示意设施编号为 1003055 的 pm2.5 的监测表
create table if not exists eg_pm_25_1003055 using s_dust_history_data tags('1003055','1','18113001',true);
create table if not exists eg_pm_10_1003055 using s_dust_history_data tags('1003055','2','18114001',false);
insert into eg_pm_25_1003055 (ts,measured_value,id) values("2021-07-29 21:43:22",7.0,123);
insert into eg_pm_10_1003055 (ts,measured_value,id) values("2021-07-29 21:43:22",6.0,124);
insert into eg_pm_25_1003055 (ts,measured_value,id) values("2021-07-29 21:43:22",9.0,123);
注:
1. 全列模式写入速度会远快于指定列,倡议尽可能采纳全列写入形式
2. 批量插入数据,写入速度更快(最多反对同时插入 32000 条左右,和 SQL 长度无关)
3. 对于反复的数据,疏忽前面插入的数据
数据查问
select * from s_dust_history_data where ts > '2021-07-29 00:00:00' and ts < '2021-07-30 00:00:00' and signal_code = '18113001';
Spring Boot 整合 TDengine
当用户须要查问工地设施扬尘数据时,扬尘数据将通过定时工作从第三方接口中定时拉取保留至咱们零碎的数据库。因为扬尘数据的量较大,为千万甚至上亿级别,而系统配置相干数据的数据量较小,因而咱们抉择将扬尘数据和系统配置数据拆散——扬尘数据应用 TDengine 进行存储,系统配置数据采纳 MySQL 进行存储。
本文应用 MybatisPlus 作为长久层框架,同时接入 TDengine 和 MySQL,做双数据源配置。下文中将重点讲述 TDengine,MySQL 相干内容将省略。
1. taos-jdbcdriver 的抉择
依据官网找到 taos-jdbcdriver 的对应版本,本文应用的 taos-jdbcdriver 版本是 2.0.22。
<dependency>
<groupId>com.taosdata.jdbc</groupId>
<artifactId>taos-jdbcdriver</artifactId>
<version>2.0.22</version>
<scope>runtime</scope>
</dependency>
【问题】 最开始应用的是较高的版本,后果呈现无奈失常拜访的状况,最终升高 taos-jdbcdriver 版本后得以解决。
2. 双数据源配置
在 Spring Boot yml 中配置双数据源,应用 druid 连接池,将 TDengine 设置为主数据库,MySQL 设置为副数据库。
spring:
datasource:
dynamic:
druid:
initial-size: 10
min-idle: 10
max-active: 100
max-wait: 60000
test-while-idle: false
primary: td-engine
strict: false
datasource:
td-engine:
driver-class-name: com.taosdata.jdbc.TSDBDriver
url: jdbc:TAOS://address:port/dbname
username: dbusername
password: dbpassword
mysql:
driver-class-name: com.mysql.cj.jdbc.Driver
url: ...
username: ...
password: ...
3. 代码编写
外围逻辑是第三方数据的定时拉取以及在本零碎进行的查问,此处次要介绍 TDengine 的 mapper 写法。
官网提到 TDengine 全列模式写入速度会远快于指定列,倡议尽可能采纳全列写入形式;而扬尘数据的品种多样,因而咱们采纳动静表名 + 批量插入的形式。每次拉取数据时,以设施和扬尘数据品种为维度创立 tags,同时对该维度的数据进行数据插入。
Mapper
a. 创立 Tags
<insert id="createTags" parameterType="TagsEntity">
create table if not exists #{tags 名称}
using 超级表名称 tags
(#{tagsColumn1Value},
...
#{tagsColumnNValue})
</insert>
b. Tags 插入单条数据
<insert id="insert" parameterType="TagsEntity">
insert into #{tags 名称}
(#{tagsColumn1},
...
#{tagsColumnN})
values
(#{tagsColumn1Value},
...
#{tagsColumnNValue})
</insert>
须要留神的是,TDengine 在进行全列写入时,必须为数据表的每个列都显式地提供数据,并且一次插入的数据是有下限的,否则会报错,倡议在正式插入之前测试一下全列写入的下限。
<insert id="batchInsert" parameterType="TagsEntity">
insert into #{tags 名称}
values
<foreach collection="list" item="data">
(#{data.tagsColumn1Value},
...
#{data.tagsColumnNValue})
</foreach>
</insert>
JavaBean
如需查问扬尘数据,创立一个和超级表绑定的实体类即可,外面应该蕴含超级表自身的属性以及 tags 的属性,能够间接应用 MyBatisPlus 的长久层办法进行查问。
@Data
@TableName(tbname)
public class SuperTableEntity {
private String colunm1;
...
}
【问题一】 在编写完代码后只管查问不会出错,但插入和创立 tags 会产生谬误,起初发现此处是 DNS 解析异样,因为 TDengine 配置了 FQDN,因而应该在 hosts 中配置映射关系,之后能力进行失常的插入和创立操作。
【问题二】 在进行第三方数据同步时,因为第一次是同步历史数据,因而插入 TDengine 的数据量较大。只管 TDengine 自身反对的全列模式写入曾经晋升了不少效率,但如果代码中的批量插入持续应用一般 for 循环,插入效率依然较低,这里能够通过切割数据和多线程的形式进行实现。
private void runner(List<Entity> list, int dealSize) throws Exception {if (!CollectionUtils.isEmpty(list)) {
// 数据总的大小
int count = list.size();
// 每个线程数据集
List<Entity> threadList = null;
// 线程池
int runSize = (count / dealSize) + 1;
ThreadPoolExecutor executor = new ThreadPoolExecutor(
runSize,
350,
30L, TimeUnit.SECONDS,
new SynchronousQueue<>());
CountDownLatch countDownLatch = new CountDownLatch(runSize);
for (int i = 0; i < runSize; i++) {
// 计算每个线程执行的数据
int startIndex = (i * dealSize);
if ((i + 1) == runSize) {threadList = list.subList(startIndex, count);
} else {int endIndex = (i + 1) * dealSize;
threadList = list.subList(startIndex, endIndex);
}
//TODO 这里写本人的线程工作
executor.execute(myThread);
}
// 计数
countDownLatch.await();
// 敞开线程池
executor.shutdown();}
}
在应用双数据源时,Controller 和 Dao 与个别的 Spring Boot + MyBatis 无异,次要在于 Service,因为设置的 primary 数据库是 TDengine,所以长久层默认会拜访 TDengine 数据库,如果要切换,须要在 service 的 class 或办法上增加注解 @DS(databaseAlias),括号中填写 yml 中配置的数据库别名,如 td-engine、mysql 等,通过这种形式来抉择须要拜访的数据库。primary 数据库能够省略 @DS。
@DS("td-engine")
public TestEntity get() {return testDao.get();
}
TDengine 数据迁徙
当咱们须要将扬尘数据从公司本地服务器迁徙数据至华为云服务器,文中应用 TDengine 自带的 dump 工具进行数据迁徙。
参考文档: https://www.taosdata.com/blog/2020/03/09/1334.html
DUMP 命令帮忙信息
[root@hnbhbt ~]# taosdump --help
要害参数:
-h: 主机名称
-o: 导出文件门路
-i: 导入文件门路
-u: TDengine 用户名
-p: TDengine 明码
-A: 导出所有数据库的数据
-B: 导出指定数据库(可选多个数据库)
-S: 开始工夫工夫戳
-E: 完结工夫工夫戳
-T: 指定导出数据时,启动的线程数。倡议设置成机器上 core 的 2 倍
1. 数据导出
[root@hnbhbt ~]# taosdump -h hostname -o /dump/data-210824 -u username -p password -A -S 1598889600000 -E 1628956800000 -T 500 -N 100
2. 数据导入
[root@hnbhbt ~]# taosdump -u username -p password -i ~/data-210824 -T 4
【问题】 此处在配置 hostname 时应该填写 FQDN,如果不填写或者填写服务器 IP,将会产生谬误。
集群搭建
参考网址:
TDengine 集群装置、治理 https://www.taosdata.com/cn/d…
应用 TDengine 进行报警监测 https://www.taosdata.com/blog…
常见问题 https://www.taosdata.com/cn/d…
一篇文章说分明 TDengine 的 FQDN https://www.cnblogs.com/taosd…
Linux 配置 ntp 工夫服务器(全)https://www.cnblogs.com/quchu…
告警模块搭建
参考网址:
Alertmanager 配置概述
https://yunlzheng.gitbook.io/…
深刻 Alertmanager 概念与配置介绍
https://www.cnblogs.com/gered…
alertmanager 配置文件详解(四) https://www.soulchild.cn/2073…
java 利用钉钉机器人向钉钉群推送音讯
https://www.cnblogs.com/zhouh…
Alertmanager 企业微信配置 https://www.jianshu.com/p/135…
小结
应市质安站的监管要求以及蓝天办对空气污染治理的督查要求,市内所有工地的空气质量数据及乐音数据均需接入政府监管平台、纳入治理中。监控数据的特点就是时序、结构化、简略但量大,在解决这类数据上,TDengine 能够说是量身定做。搭载 TDengine 后,监控数据上报后的实时展现、历史回溯都十分快,加上其自身轻量的特点,对于缩减我的项目开发运维老本也十分有帮忙,完满满足了业务的需要。