TDengine 在“一图一库”中的应用,助力交通运输实现信息化转型

小 T 导读:在某大交通数据资源管理系统及相关应用“一图一库”的建设中,存在大量的时序数据应用场景,其中最为关键的就是车辆运行产生的时序数据的存储与使用,在选型调研后决定采用 TDengine Database。本文详细汇总了关于集群架构落地、写入查询效果的相关经验及建议。

公司简介

北京金海乐游软件有限公司是一家以计算机软件架构开发为核心,实施计算机软硬件系统集成的现代科技企业。公司从事交通运输行业系统软件研发,技术覆盖且不限于 Java Spring 框架(可选技术框架:C/C++、Python、Go)行业业务逻辑实现、TransCAD\TransModeler\超图\Arcgis 等商业软件的二次开发和算法实现、大数据分析及数据中台、 交通资产管理。

一、项目背景

为了强化全市交通运输管理、统筹综合交通发展、提升交通运行和管理效率,某市级管理单位建立了大交通数据资源管理系统及相关应用 “一图一库”。其中“一库”部分主要内容包括:数据接入、数据存储、数据共享;“一图”部分主要内容包括:GIS 信息及其关联数据信息在二维、三维地图上的形象表达。

该大交通数据资源管理系统本质是为某市交通运输行业建设高效可用的行业数据中台系统,其基本架构如下:

基本架构

在数据中台的建设中,存在大量的时序数据应用场景,其中最为关键的就是车辆运行产生的时序数据的存储与使用。如下图所示,综合交通运行监测系统中,GPS 时序数据是及其重要的数据资源:

综合交通运行监测系统

由出租车、网约车、公交车、轨道、水运、长短客运、两客一危、铁路运输的车辆船舶实时上传运行的相关数据,均具备时序数据特征,每日的入库数据量轻松突破亿级大关,一线城市或省级区域的车辆船舶运行数据甚至可达到数亿甚至数十亿级别,如何高效地将时序类数据入库成为交通运输行业数据中台的一个核心诉求。

另外,交通运输行业信息化业务中还有对于车辆实时位置高效查询的核心诉求。举一个典型的用例,用户需要频繁获得当日上线车船(数万至数十万)的数量、最终位置信息、营业额度等信息,此种类型的查询需要高效的返回结果集(万级车船查询须在秒级)。而且随着信息化的进程,用户会频繁地出现各种新的时序数据查询需求,需要快速高效的实现与部署。

第三,从交通行业数据的重要性和敏感性出发,数据存储的可靠性、可扩张性也是极为重要的核心诉求。

二、数据库选型及落地过程

1. 为什么是 TDengine?

在选型初始,我们考虑了三个数据库(Database),分别是 InfluxDB、ClickHouse 和 TDengine。

  • InfluxDB:成熟的老牌时序数据库,但是重要的集群功能需要商业版本,考虑到国外商业软件的特殊性质,从审批到付款以及后续安全性都存在一定风险。
  • ClickHouse:俄罗斯开发的高性能数据库,主要问题在于开源社区主要以俄语为主,其非标准化 SQL 的学习成本较高、集群维护成本高。
  • TDengine:国产化数据库、中文开源社区,极佳的写入速度以及便于维护的集群架构,这三点原因最终促使我们选择 TDengine 作为项目的时序数据库。

参考选型文章:

  • TDengine Testing Report
  • System Properties Comparison ClickHouse vs. InfluxDB vs. TDengine

2. 集群架构落地

使用 5 台服务器搭建 TDengine Database 的 Dnode 集群,Mnode 与数据库的副本数均设定为 3。

在集群的设定初期,由于当前版本 Mnode 个数的缺省值由之前的 3 个变更成为了 1 个,系统 Mnode 最初没有副本,使用以下的方法进行安全的重启维护,将 Mnode 总数升级为 3 个,此方法由官方社群中提供的 TDengine 集群版升级步骤变更而来:

0.确保集群节点状态正常(show dnodes;),读写无问题
1.在所有节点停止数据库服务 systemctl stop taosd
2.备份数据文件目录下的所有内容 到数据文件目录之外
3.分别 cd 进入各个节点的数据文件目录
4.tree 命令检查所有 vnode 目录下的 wal 目录是否为空
5.如果为空,进入步骤 7
6.如果非空,启动数据库进程,再关闭,直到 wal 全部为空
7.在数据库服务 taosd 停止的状态下,分别在所有节点修改配置文件,将 numOfMnodes 的值设为3
8.分别启动所有节点的 taosd 服务,systemctl start taosd。
9.show dnodes 检查节点状态
10.检查数据

3. 数据写入架构落地

由于我们的业务开发框架使用的是 Srping 框架,在使用 TAOS-JDBCDriver 进行开发时,可以选择两种方式进行数据入库——JDBC-JNI 方式或者是 JDBC-RESTful 方式。在 TDengine 官网,明确记载了“JDBC-RESTful 性能是 JDBC-JNI 的 50%~90%”,所以,我们选择了 JDBC-JNI 方式进行多线程入库。

在 JDBC-JNI 方式中,依然有两种实现方式,在数据库连接池(Hikari、druid)的基础上,原生 SQL 执行写入或者是使用 ORM 框架(MyBatis等)执行写入。在试运行初期,我们使用了 ORM 框架进行数据写入,在当前的数据写入量之下,并没有太大的问题。

但是,参考涛思数据副总肖波在社区群中沟通中的意见:“ORM 框架大多数面向关系库开发场景,每秒几万的吞吐量对它们来说就很大了,但在时序数据写入场景中,这连塞牙缝都不够,设计满足的应用场景不同导致适配度有差异,但查询影响不大”,我们认识到 ORM 框架本身可能存在性能瓶颈,因此在未来的版本中,我们使用了数据库连接池(Hikari、druid)+原生 SQL 执行写入为主要写入模式。

三、接入 TDengine 的效果展示

1. 写入效果

项目的目标写入量为 1 亿条/天,每秒钟写入 1158 条左右,我们通过 TDengine 自带的 log 功能进行分析,确认写入效率。由下图可以看出,五节点构成的集群中,目前瞬时写入能力取不精确的最大值,也就是 dn1 节点的 23107 条。log.dn 表中数据采集的周期是 30 秒,由此可知,dn1 的实测瞬时最大写入量是 770 条/秒。加之五节点的集群在分布式插入的架构下,770*5=3850 条/秒的数据插入效率是完全可以保障的,完全满足了我们业务需求。至于本集群的插入性能上限,应在此实测值的 100 倍以上,并且有极大的增长空间。

dn1 的实测瞬时最大写入量是 770 条/秒

这里说明一下 log.dn 表是及其重要的一张 TDengine 自带的运行状态数据表,我们可以通过此表对 TDengine 的运行状态进行监视,后面在查询资源占用情况的时候,我们还会用到这张表。log 表字段的说明如下图:(据官方社区工作人员表示,后面新版本的 TDinsight 是更好的监控工具,有机会打算试用一下)

log 表字段的说明1
log 表字段的说明2

2. 查询效果

所有车辆最新位置信息的查询是交通运行监控中的重中之重,最初“使用何种查询语句实现高效查询”是令我们非常困扰的一件事,后面在 TDengine 社区团队的帮助下,我们利用了隐藏字段名 tbname 和 group by 方法,高效地查询了车辆的最新定位信息。从下图可以看到,频繁查询的情况下,接近六万辆车的位置信息,只用了不到1秒的查询时间,简单而又高效,完全符合我们的业务需求

接近六万辆车的位置信息
只用了不到1秒的查询时间

数据统计分析也是各种业务系统中需要广泛实装的一个功能。我们再看一个例子,一个 64 天数据量的表,进行每日数据条数的降维统计,所需时间也不到 1 秒:

一个 64 天数据量的表
每日数据条数的降维统计,所需时间也不到 1 秒

在合理的 SQL 设计支持之下,TDengine 的查询效率完全可以满足时序类数据的高效查询需求,大大简化了开发难度,降低了运维成本,整个团队都为此感到满意。

3. 资源占用

下图中罗列了一日内各个节点的 CPU、内存、带宽、IO 读写的相关数据(最大采样值),其资源消耗尤其是 CPU 方面的消耗是非常稳定和可控的:

各个节点的 CPU、内存、带宽、IO 读写的相关数据
各个节点的 CPU、内存、带宽、IO 读写的相关数据

四、结语

在本次开发中,TDengine Database 展现出的性能效果非常显著,推动了交通行业海量时序数据业务快速高质地落地,极大地降低了开发与运维成本。对于堪称国货精品的 TDengine,我们愿意付出更多的耐心与信心,甚至愿意参加到开源社区的开发活动中去,为其建立一个良好的社区生态而努力。 对于 TDengine 产品本身,我们也有更多的期许:

  • 在目前的高迭代开发期,尤其是对集群客户,提供不间断服务的无缝升级功能
  • 建议 TDengine 开展培训、认证、服务分成体系,培养更多的认证服务代理商
  • 提供更多的专业领域函数,比如说空间函数库,功能上可以参考 MySQL 的空间函数库
  • 开放第三方的函数插件市场,在插件开发规范的基础上,会有更多的用户贡献出专业领域的函数插件

借助中国的巨大市场,愿 TDengine 早日成长为时序数据库领域的 Oracle!

作者 | 王扬 北京金海乐游软件有限公司 技术主管