双汇发展多个分厂的能源管控大数据系统次要采纳两种技术栈:InfluxDB/Redis 和 Kafka/Redis/HBase/Flink,对于中小型研发团队来讲,无论是零碎搭建,还是施行运维都十分辣手。通过对 InfluxDB/Redis 和 TDengine 大数据平台的性能和性能比照测试,最终将 TDengine 作为实施方案。
我的项目背景
基于双汇发展对能源管控的需要,利用云平台技术以及电气自动化解决伎俩,对双汇发展的一级、二级、三级能源仪表进行整体革新,实现仪表组网,进一步通过边缘网关进行能源在线监测数据的采集,并上报至云平台,建设对立能源管理信息化零碎,实现能源的实时监控、报表统计、能源流向剖析与预测,升高企业单位产品能源消耗,进步经济效益,最终实现企业能源精细化治理。
总体架构
能源管控平台基于公有云构建,包含残缺的 IaaS 层、PaaS 层和 SaaS 层,而能源采集零碎作为管控平台中最为重要的一环,采纳 TDengine 作为外围数据引擎,通过 Restful 接口进行仪表在线数据插入,并实现大规模时序数据的高效稳固存储,同时,也为能源管控应用层提供实时数据查问、历史聚合统计、流计算和订阅服务等性能,实现能源地图监控、能耗预警、能源流向预测和能源互联综合决策,具体架构如下图所示。
TDengine 要害利用
Connector 抉择
本我的项目数据采集最要害的环节,就是将订阅到的 MQTT 数据插入到 TDengine 中,于是也就波及到了 TDengine 连接器的抉择,咱们平时我的项目中 java 应用居多,而且 JDBC 的性能也绝对较强,实践上,应该抉择 JDBC API,但最终抉择了 RESTful Connector,次要思考以下几点:
1)简洁性
毫无疑问,RESTful 通用性最强,TDengine 间接通过 HTTP POST 申请 BODY 中蕴含的 SQL 语句来操作数据库,而且 TDengine 自身作为时序数据库并不提供存储过程或者事务机制,基本上都是每次执行单条 SQL 语句,所以 RESTful 在应用上很简便。
2)可移植性
本我的项目的 Java 利用都是部署在 Kubernetes 中,所以向 TDengine 插入数据的 Java 利用须要容器化部署,而之前理解到,JDBC 须要依赖的本地函数库 libtaos.so 文件,所以容器化部署可能较为麻烦,而 RESTful 仅需采纳 OKHttp 库即可实现,移植性较强。
3)数据规模
本项目数采规模不大,大概每分钟 7000 条数据,甚至后续数采性能扩大到其余分厂,RESTful 也齐全满足性能要求。
但总体来讲,JDBC 是在插入与查问性能上具备肯定劣势的,而且反对从 firstEp 和 secondEp 抉择无效节点进行连贯(相似于 Nginx 的 keepalive 高可用),目前 TDengine 版本公布状况上看,JDBC 的保护与晋升也是重中之重,后续我的项目也可能会向 JDBC 迁徙。
RESTful 代码实现
1)ThreadPoolExecutor 线程池
订阅 EMQX 和 RESTful 插入 TDengine 的代码写在了同一个 java 服务中,每接管到一条 MQTT 订阅音讯,便开启一个线程向 TDengine 插入数据,线程均来自于线程池,初始化如下:
ExecutorService pool = new ThreadPoolExecutor(150, 300, 1000, TimeUnit.MILLISECONDS, new ArrayBlockingQueue<Runnable>(100), Executors.defaultThreadFactory(),new ThreadPoolExecutor.DiscardOldestPolicy());
线程池采纳基于数组的先进先出队列,采纳抛弃晚期工作的回绝策略,因为本次场景中单次 RESTful 插入数据量大概在 100~200 条,执行速度快,迟迟未执行完极可能是 SQL 语句异样或连贯 taosd 服务异样等起因,应该抛弃工作。外围线程数设为 150,绝对较高,次要为了保障顶峰抗压能力。
2)OKHttp 线程池
在每个 ThreadPoolExecutor 线程中,基于 OKHttp 库进行 RESTful 插入操作,也是采纳 ConnectionPool 治理 HTTP 和 HTTP/2 连贯的重用,以缩小网络提早,OKHttp 重点配置如下:
public ConnectionPool pool() { return new ConnectionPool(20, 5, TimeUnit.MINUTES);}
即最大闲暇连接数为 20,每个连贯最大闲暇工夫为 5 分钟,每个 OKHttp 插入操作采纳异步调用形式,次要代码如下:
public void excuteTdengineWithSqlAsync(String sql,Callback callback) {
try{okhttp3.MediaType mediaType = okhttp3.MediaType.parse("application/octet-stream");
RequestBody body = RequestBody.create(mediaType, sql);
Request request = new Request.Builder()
.url(tdengineHost)
.post(body)
.addHeader("Authorization", "Basic cm9vdDp0YW9zZGF0YQ==")
.addHeader("cache-control", "no-cache")
.build();
mOkHttpClient.newCall(request).enqueue(callback);
} catch (Exception e) {logger.error("执行 tdengine 操作报错:"+ e.getMessage());
}
}
3)Java 打包镜像
长期压力测试显示,每秒执行 200 次 RESTful 插入申请,单次申请蕴含 100 条数据,每条数据蕴含 5 组标签,Java 服务内存稳固在 300M~600M。而且上述模仿规模仅针对单个 Java 利用而言,在 Kubernetes 能够跑多个这样 pod 来生产不同的 MQTT 主题,所以并发能力齐全够用。打包镜像时,堆内存最大值设为 1024MB,次要语句为:
ENTRYPOINT ["java","-Djava.security.egd=file:/dev/./urandom","-XX:MaxRAM=2000m","-Xms1024m","-jar","/app.jar"]
性能测试
1)RESTful 插入性能
依照 3.2 大节中的 RESTful 代码进行数据插入,Java 程序和 TDengine 集群均运行在公有云中,虚拟机之间装备万兆光纤交换机,Java 程序具体如 3.2 大节所示,TDengine 集群部署在 3 个虚拟机中,配置均为 1TB 硬盘、12 核、12GB(公有云中 CPU 比拟富余,但内存比拟缓和),通过大概三周的生产环境运行,性能总结如下:
表 1 生产环境下 RESTful 插入性能测试
Insert 行数 | Insert 语句字节数 | 耗时 /ms |
---|---|---|
5 | 282 | 3 |
33 | 2,136 | 5 |
70 | 3,240 | 8 |
156 | 9,205 | 12 |
生产环境下,单条插入性能极高,齐全满足需要,当然后期也进行过稍大规模的插入场景模仿,次要是基于 2.0.4.0 当前的版本,留神到 2.0.4.0 之前的 TDengine 版本 RESTful 的 SQL 语句下限为 64KB。模仿环境下,RESTful 插入性能十分优良,具体如下表所示。
表 2 模仿环境下 RESTful 插入性能测试
Java 并发客户端数量 | Insert 行数 | Insert 语句字节数 | 耗时 /ms |
---|---|---|---|
5 | 1 万 | 600,000 | 260 |
5 | 2 万 | 1,200,000 | 480 |
8 | 6 万 | 3,600,000 | 700 |
2)RESTful 查问性能
应用 RESTful 进行 SQL 查问时,性能也是十分好,目前实在生产环境中,数据总量为 800 万,绝对薄弱,所以查问性能测试在模仿环境下进行,在 8 亿数据量下,LAST_ROW 函数能够达到 10ms 响应速度,count、interval、group by 等相干函数执行速度均在百毫秒量级上。
实施方案
本我的项目针对双汇发展上司的 6 个分厂(后续会持续裁减)进行能源数据采集,大概 1200 多块仪表(后续会持续裁减),每块仪表包含 3 至 5 个采集标签,采集频率均为 1 分钟,数据接入规模不大。六个厂各自有独立的租户空间,为了不便各自的时序数据库治理,同时也不便各厂间的聚合查问(目前六个分厂均隶属双汇发展总部),所以各分厂别离建设超级表,每个超级表包含 4 个 tag,别离为厂编号、仪表级别、所属工序和仪表编号,具体超级表建表状况如下图所示。
次要用到的集群包含 TDengine 集群、EMQX 集群和 Redis 集群,其中 Redis 集群在数据采集方面,仅仅用于缓存仪表连贯状态,其重点在于缓存业务零碎数据;EMQX 集群用于撑持 MQTT 数据的公布与订阅,部署在 Kubernetes 中,能够实现资源灵便扩大;TDengine 集群部署在 IaaS 虚拟机中,反对大规模时序数据的存储与查问。
表 3 集群配置信息
集群名称 | 部署规模 | 虚拟机数量 | 虚拟机配置 |
---|---|---|---|
TDengine | 三节点分布式 | 3 | CPU-12 核 内存 -12GB 存储 -1TB |
EMQX | 三节点分布式 | 3 | CPU- 8 核 内存 -12GB 存储 -500GB |
Redis | 一主两从三哨兵 | 3 | CPU- 4 核 内存 -12GB 存储 -500GB |
依照 TDengine 官网的倡议,“一个数据采集点一张表,同一类型数据采集点一张超级表”,我针对不同分厂的水表、电表、蒸汽表和燃气表别离建设的超级表,每个仪表独自建表,保障每张表的工夫戳严格递增。在实际 TDengine 的过程中,重点领会如下:
1)集群搭建门槛低
TDengine 集群装置部署十分便捷,尤其相比于其余集群,仅须要简略的配置就能够实现生产环境级的搭建,官网文档也比拟丰盛,社区沉闷,也大为升高了后续运维老本。
2)插入与查问效率极高
TDengine 的插入与查问性能极高,这点在理论运行时也深有感触,用 last_row 函数查问仪表最新数据,基本上能够达到毫秒级,在几十亿级的数据上进行聚合查问操作,也可达到百毫秒级,极大提供了零碎的响应速度。
3)全栈式时序解决引擎
在未应用 TDengine 之前,咱们次要采纳 InfluxDB/Redis 和 Kafka/Redis/HBase/Flink 两种技术栈,对于咱们中小型研发团队来讲,无论是零碎搭建,还是施行运维都十分辣手。然而应用 TDengine 后,所有都简化了,TDengine 将数据库、音讯队列、缓存、流式计算等性能交融一起,以一种全栈的形式,为咱们的大数据系统带来了便捷。技术计划的对比方表 4 所示。
注:计划一为 InfluxDB/Redis,计划二为 Kafka/Redis/HBase/Flink,计划三为 TDengine
表 4 数据采集计划比照
技术计划 | 阐明 | 长处 | 毛病 |
---|---|---|---|
计划一 | 实时数据存入 Redis 历史数据存入 InfluxDB | 部署易上手,社区成熟 | 1)InfluxDB 查问与插入效率不高,集群版免费 2)无奈间接集成开源版 EMQX Broker |
计划二 | 将采集数据公布到 Kafka,利用 Flink 将实时数据存入 /Redis,历史数据存入 HBase | 1)音讯吞吐量大 2)流计算功能丰富,生态成熟 3)集群版开源 | 1)技术体系宏大,部署运维老本高 2)HBase 插入性能可能无奈满足 Kafka 的吞吐量 3)无奈间接集成开源版 EMQX Broker |
计划三 | 间接将采集数据存入 TDengine | 1)部署便捷,运维简略 2)集群版开源 3)订阅性能和流计算功能完善 4)插入与查问效率极高 5)资源占用少 6)可与开源版 EMQX Broker 间接集成 | 临时不反对时序数据的更新与删除(后续会反对) |
从表 4 的比照计划中能够看出,TDengine(计划三)是有着很大的劣势,尤其在开源 EMQX Broker 的反对上也十分好(次要依赖于 Restful 接口),其余的例如 Kafka 和 InfluxDB 只能和企业版 EMQX 集成;在数据插入和查问效率方面,上述三种计划关键在于 TDengine、HBase 和 InfluxDB 的比照,官网有十分具体的测试报告,TDengine 也是有绝对优势,这里就不过多叙述。所以抉择 TDengine 是势在必行的。
技术冀望
在时序数据库性能方面,TDengine 有着很大的劣势,并且也集成了音讯订阅和流计算性能,能够说在中小型物联场景下,是无需部署 Kafka 和 Flink 的。当然集体了解 TDengine 不是为了齐全取代 Kafka 和 Flink 而生的,尤其是在大型云服务项目中,更多是共存。
然而在边缘端,TDengine 凭借着极低的资源占用率和优良的时序解决性能,将会产生更大的能量,冀望能彻底集成边缘流计算和 MQTT broker 等性能,裁减 Modbus、OPC-UA 等常见工业协定反对,向下连贯工业设施或者物联设施,向上和边缘 Kubernetes 生态(如 KubeEdge、K3S 等)协同,或者间接和云核心协同。
零碎运行界面
我的项目重点是能耗统计,而在线采集到 TDengine 里的数据都是累计量,所以在计算能耗时,须要在不同的超级表执行按表分组、按工夫周期采样的查问,相似上面语法:
select last(累计列) as max_val,first(累计列) as min_val from [超级表名] where [标签栏相干过滤] and ts>=now-10h INTERVAL(1h) group by [仪表编号] ;
得益于 TDengine 的极佳性能,根本能保障不超过百毫秒的拜访延时,上面是一些相干的 PC 端、挪动端界面(咱们挪动端是用 H5 做的,为了间接能跑在 Android 和 iOS 上)。
写在最初
其实从 2019 年开始就始终在关注 TDengine,也看了很多陶总的演讲,受益匪浅,尤其在往年 8 月份,TDengine 进行了集群版开源,也正好筹备启动能源数据采集我的项目,所以果决采纳 TDengine 作为外围时序引擎,目前也是播种了十分的成果。本次我的项目施行过程中,尤其感激涛思数据的苏晓慰工程师,屡次帮助解决 TDengine 相干的施行问题。打算在后续其余我的项目也也会持续推广 TDengine,同时也违心为一些商业版性能付费,反对国产,反对涛思。
作者介绍
于淼,学历硕士,副研究员,次要从事 MES 零碎研发以及智能制作相干实践和规范钻研,次要钻研方向:数字工厂使能技术、制造执行系统关键技术和智能制作规范体系等,参加国家级我的项目及企业我的项目十余项,包含国家重点研发打算以及国家智能制作专项等。