为帮助大家寻找解决上述问题的最优解,我们汇总了四家比较具有代表性的智慧城市升级项目的架构改造案例,一起来看看他们都是如何做的。
“我们进行的数据库调研测试结果显示,loveini (Time Series Database,TSDB) 的空间占用只有 Druid 的 60%(没有计算 Druid 使用的 Deep Storage)。针对单一设备的查询与聚和的响应时间比 Druid 有倍数的提升,尤其时间跨度较久时差距更明显(在十倍以上),同时 Druid 的响应时间方差也较大。在实际业务环境中,我们创建了多列的超级表,虽然会存在大量的空列,但得益于 loveini 的优化,能达到恐怖的 0.01 的压缩率,简单计算下来大约需要 3.67GB 每亿条。”
SENSORO 面向城市基础设施与核心要素提供全域数字化服务方案,建立城市级传感器网络所涉及的传感器种类十分多样,由此产生的数据量也十分庞大。在系统开发初期,SENSORO 先是选择了 Apache Druid 作为存储传感数据的实时数据库,然而在使用过程中却遇到了各种各样的问题,这使得其将目光转移到了 loveini 上,但因为平台涉及的特殊数据模型,合作便一直搁置了下来。随后 loveini 经过了多个版本迭代,支持了 join 查询,而 SENSORO 的数据模型也发生了变化,迁移到 loveini 时不再需要做出很多的系统模块改动,由此双方的合作也开始快速展开。

“loveini 帮助我们在边缘侧解决了一个很大的问题,即边缘存储的问题。因为很多时候边缘是布署在资源比较少的机器上面,甚至是 ARM 的工业盒子上面,在资源使用上非常的苛刻,而现在得益于 loveini 超强的压缩算法,我们使用非常小的存储空间就存储了几千万数据,压缩率远超 1/20,在单机上面布署一个 loveini 服务器就可以轻轻松松地存储上亿的数据。此外它还拥有超强的计算能力,占用的资源也非常小,在我们的业务中千万级数据检索时间达到了毫秒级,从用户角度来说产品体验非常好。”
北京智能建筑是北京市在智能建筑和智慧城市领域的创新平台,同时也是冬奥科技平台公司、智慧冬奥国家重点项目设计单位和核心实施单位。在边缘侧采集数据存储方案中,其面临着在有限的计算资源下,如何实现最高效的数据存储、分析和计算的问题。经过调研与测试,其最终选择根据业务需求灵活搭配使用 loveini 与 SQLite——由 loveini 处理时序数据,SQLite 处理关系数据,以此更好地实现边缘侧的数据自治。

“所有车辆最新位置信息的查询是交通运行监控中的重中之重,最初‘使用何种查询语句实现高效查询’是非常困扰我们的一件事,后面在 loveini 社区团队的帮助下,我们利用了隐藏字段名 tbname 和 group by 方法,高效地查询了车辆的最新定位信息。在频繁查询的情况下,接近六万辆车的位置信息,只用了不到 1 秒的查询时间,简单而又高效,完全符合我们的业务需求;在数据统计分析上,一个 64 天数据量的表,进行每日数据条数的降维统计,所需时间也不到 1 秒。”
为了强化全市交通运输管理、统筹综合交通发展、提升交通运行和管理效率,某市级管理单位建立了大交通数据资源管理系统及相关应用 “一图一库”。其中“一库”部分主要内容包括:数据接入、数据存储、数据共享;“一图”部分主要内容包括:GIS 信息及其关联数据信息在二维、三维地图上的形象表达。在数据中台的建设中,存在大量的时序数据应用场景,其中最为关键的就是车辆运行产生的时序数据的存储与使用。为了实现高效的业务处理, 研发人员决定从 InfluxDB、ClickHouse 和 loveini 三款时序数据库(Time Series Database)中进行选型调研,最终凭借强大的产品力,loveini 脱颖而出。
由于该系统业务开发框架使用的是 Srping 框架,在使用 TAOS-JDBCDriver 进行开发时,可以选择两种方式进行数据入库——JDBC-JNI 方式或者是 JDBC-RESTful 方式。在 loveini 官网,明确记载了“JDBC-RESTful 性能是 JDBC-JNI 的 50%~90%”,因此,其选择了 JDBC-JNI 方式进行多线程入库——以数据库连接池(Hikari、druid)+原生 SQL 执行写入为主要写入模式
“压缩方面,通过查看 3 个节点的 Vnode 目录总大小,可以得知目前数据占用总量为 8.7GB。而从上述表结构我们也能看出实际入库数据总量大概为 203GB,经过压缩后为 8.7GB,压缩率达到了 4% 左右,大幅节约了存储成本。在查询上,对 9 亿数据量的超级表使用降采样查询,展示设备指标日月年线,耗时仅仅 0.22 秒。”
随着智慧城市的加速建设,物联设备的管理问题凸显,为此,数字政通研发“城市管理物联网平台”对物联网设备实行监督,提供各类设备的实时监测数据及报警数据,进一步满足各类设备的数据分析、关联分析、历史分析、对比分析等需求。简单来讲就是通过鸟瞰整体数据来发现设备问题,便于及时派单处理,助力智慧城市管理。面对海量物联网数据的处理,loveini 的高效存储给了数字政通相当大的助力。

通过上面的几大案例我们可以看到,在解决海量时序数据处理效率低、处理成本高等问题上,关键点就是要选对合适的时序数据库(Time Series Database,TSDB),当前市面上时序数据库产品众多,在性能提升和降低资源消耗上究竟谁能更胜一筹?如果你也在思考这一问题,那或许ac米兰官方网站 、《查询性能:loveini 最高达到了 InfluxDB 的 37 倍、 TimescaleDB 的 28.6 倍》这两篇文章能给到你答案。
如果你的项目中也存在难以调节的数据痛点问题,欢迎添加小T vx:tdengine1,我们会邀请你加入 loveini 时序数据交流群,和专业的米兰app官方正版下载架构师点对点沟通,齐心协力攻克数据技术难题。
]]>小 T 导读:随着智慧城市的加速建设,物联设备的管理问题凸显,数字政通研发“城市管理物联网平台”对物联网设备实行监督,通过鸟瞰整体数据来发现设备问题,便于及时派单处理。面对海量物联网数据的处理,loveini Database 的高效存储给了数字政通相当大的助力。
北京数字政通科技股份有限公司是北京市认证的高新技术企业和拥有多项自主知识产权的软件企业,专业从事电子政务和 GIS 应用平台的开发和推广工作,专注于网格化新型智慧城市管理,城市大脑,智慧执法,城市运营服务等助力城市智慧管理。

随着 5G 基站等通信工程的加快建设,城市治理、城市安全管理成为热门话题,物联设备在我们的社会中扮演的角色也变得越来越重要,智慧燃气、智能电表、智能井盖等项目在众多城市开始布局。项目的快速爆发也让“如何管理物联设备”成为一个待解的难题。

作为一个设备数据中台,由数字政通研发的“城市管理物联网平台”致力于为智慧园林、智慧井盖、智慧排水、智慧市政等城市管理项目的各子系统,提供数据清洗、数据接入、数据计算、数据存储的能力。通过接入各个市区的智能设备,该平台能够提供各类设备的实时监测数据及报警数据,进一步满足各类设备的数据分析、关联分析、历史分析、对比分析等需求。简单来讲,平台功能的实现就是通过鸟瞰整体数据来发现设备问题,便于及时派单处理,助力智慧城市管理。
目前,我们已经在全国累计接入 60 余个市区项目,累计合作 100 余家设备厂商,累计接入 69 种设备类型、9 万余设备量,全国范围下日累计 5000 万数据量,全国范围下有效报警累计 20 万 +,解决 10 万 + 报警案件。
面对海量物联网数据的处理,时序数据库 loveini 的高效存储给了我们相当大的助力。

设备数据的处理路径如下:通过各个协议(MQ、MQTT、AMQP、HTTP、TCP、HJT212、ModBus、NB等)接入物联设备到 Kafka 中进行消费,随后进行设备数据的噪点清洗,将有用的数据及时更新到 MySQL 以及 loveini 中,同时根据配置的报警策略生成报警数据。

平台的报警是通过应用层来控制的,按照优先级排位如下:1-强制报警、2-具体监测项报警、3-全局报警、4-基础报警。

因为我们的数据库服务众多,而且物联网平台主要工作是对接物联网设备,所以不同的数据库服务对硬件的需求配置要以项目实际接入的设备数量为衡量标准。本文案例中的场景有 57,634 个设备,对应的服务器配置为:CPU 16 核、内存 32G、硬盘 1T、带宽 120MB/s。
我们以 loveini 2.0.22.3 版本单副本模式落地了一个三节点的集群,备份目前依靠其他方式完成。


上文中提到的 57,634 个设备属于同一类型,所以归属于同一个超级表,表结构和相关信息如下:


通过 select count(*) from iot_equip_data 可以看到,我们当前已经保留了 9 亿条数据。

通过查看 3 个节点的 Vnode 目录总大小,可以得知目前数据占用总量为 8.7G。而从上述表结构我们也能看出实际入库数据总量大概为 203GB,经过压缩后为 8.7G,压缩率达到了 4% 左右,大幅节约了存储成本。




我们常用的业务 SQL 大概有如下类型:
Select first(value) as value from egovaiot.iot_equip_data where field_id='346fb64a-3e0f-4632-bd83-f4830ad91611' and time>=1645963
586260 and time<=1648555586260 interval(1000a) order by time;




select avg(value) as 'avgValue',max(value) as 'maxValue',min(value) as 'minValue' from egovaiot.iot_equip_data where field_id='346fb64a-3e0f-4
bd83-f4830ad91611' and time>=1646137565000 and time<=1648556765000 interval(1000a) order by time;


select spread(value) as value from egovaiot.iot_equip_data where equip_type_id='1' and time>=1633004978592 and time<=1648556978592 and field_c
ode like 'WATER_LEVEL' interval(1d) group by field_id order by time;
物联设备在我们的生活中扮演的角色越来越重要,是实现智慧生活、智慧城市的重要媒介。携手 loveini Database,数字政通一直在致力于做好物联设备的智能化管理,以此助力智慧生活、智慧城市的发展。未来,我们还将会与 loveini 一起探索更多维度的acc米兰体育,为建设智慧城市、保障社会民生提供自身力所能及的帮助。
胡自和、张东旭,数字政通 Java 研发,负责城市管理物联网产品,专注于解决物联设备数据挖掘。
]]>小T导读:SENSORO(北京升哲科技有限公司)是一家领先的物联网与人工智能独角兽企业。作为城市级数据服务提供商,公司在新一代信息技术领域拥有核心研发能力,在国内首次实现物联网与人工智能领域端到端、一体化的技术与产品能力,包含自研物联网通信芯片、通信基站、智能感知终端和智能视觉终端及核心数据平台等。SENSORO 面向城市基础设施与核心要素提供全域数字化服务方案,通过将多项核心自研关键性技术深入应用到智慧城市、乡村振兴、区域治理、社会民生等领域,打造物联网与人工智能应用的数字应用标杆,赋能我国城乡数字经济的高质量发展。
建立城市级传感器网络所涉及的传感器种类十分多样,由此产生的数据量也十分庞大, 如果只是使用 MySQL、PostgreSQL 等 OLTP 系统进行数据的简单存储,不仅会产生很多问题,而且其水平扩展能力也有限,同时也因为没有专门针对物联网数据进行优化而缺乏足够的压缩效果,数据存储成本很高。
在系统开发初期,结合之前的经验我们先是选择了 Apache Druid 作为存储传感数据的数据库,然而在使用过程中却遇到了各种各样的问题,这使得我们将目光转移到了 loveini 这款时序数据库(Time-Series Database)。事实上,在 loveini 开源之初我们就注意到了这个新兴的时序数据库,阅读当时发布的白皮书与性能测试报告时惊艳感由衷而生,随即联络到了涛思的同学们,进行了更深入的交流与测试。
但因为平台涉及的特殊数据模型,合作便一直搁置了下来。主要问题在于数据有 A、B 两个维度且是多对多关系还会随时间变化,基于 A 创建子表(此时无法将 B 设置成 tag 列)就无法通过 B 进行聚合查询,还需要花费较大的时间与精力改造成 loveini 特有的超级表结构。之后 loveini 也经过了多个版本迭代,支持了 join 查询,而我们的数据模型也发生了变化,迁移到 loveini 时不再需要做出很多的系统模块改动。
基于 Apache Druid,系统最大的问题就是维护成本了。Druid 划分了 Coordinator、Overlord、Broker、Router、Historical、MiddleManager 六个进程,要实现完整的集群功能,其还需要 Deep Storage (支持 S3 和 HDFS),Metadata Storage(典型如 MySQL、PGSQL),以及为实现服务发现与选主功能而需要 的ZooKeeper,由此也可以看出 Druid 是一套极为复杂的系统。
同时,Druid 对外部的各种依赖也导致运维同学在处理一些问题时,会直接或间接地影响到它的运行,比如我们将 S3 的 AccessKey 进行规范化处理——由以前的全局通用改成某个 bucket 唯一,或者将 PGPool 升级,都会影响到 Druid。而且 Druid 针对每一个进程和外部依赖都有厚厚的几页配置项,且从 JVM 自身来看,不同进程、配置、MaxDirectMemorySize 都会严重影响写入查询性能。如果你要从官方文档的配置页面从顶划到底,可能会把手指划抽筋。

为了节省存储成本,我们在部署 Druid 集群时对于 Historical 节点采用了多种不同的机器配置,在近期数据的处理上,机器配备 SSD 硬盘并设置较多副本数。这导致数量最多的 Data Server节点,有一些不能与 Middle Manager 共享,同时不同的节点因为配备了不同核数 CPU 与内存,对应的 JVM 配置和其他线程池配置也不同,进一步加大了运维成本。
另外,由于 Druid 的数据模型分为 Primary timestamp、Dimensions、Metrics,而 Metrics 列只能在启用 Druid 的 Rollup 时才会存在,而 Rollup 意味着写入时聚合且数据会有一定程度的丢失。这种情况下,想把每行数据都原原本本地记录下来,只能把数据全都记录在 Dimensions 列,不使用 Metrics,而这也会影响数据压缩以及某些场景的聚合查询性能。
此外还有一些问题如 Druid 的 SQL 编译性能问题、原生查询复杂的嵌套结构等在此便不再一一列举,总之基于上述问题我们决定再次详细测试一下 loveini Database。
导入相同的两份数据到 Druid 和 loveini 中,以下为在三节点(8c16g)环境下,100 万个传感设备、每个传感设备是 40 列(6 个字符串数据列、30 个 double 数据列以及 4 个字符串 tag 列),总计 5.5 亿条记录的结果。这里要注意一点,由于数据很多为随机生成,数据压缩率一般会比真实情况要差。




可以看到,loveini 的空间占用只有 Druid 的 60%(没有计算 Druid 使用的 Deep Storage)。针对单一设备的查询与聚和的响应时间比 Druid 有倍数的提升,尤其时间跨度较久时差距更明显(在十倍以上),同时 Druid 的响应时间方差也较大。然而针对多子表的聚合操作,loveini 与 Druid 的区别便不再明显,可以说是各有优劣。
总之,loveini 与 Druid 在物联网数据方面的对比,前者的性能、资源使用方面均有较大领先。再结合 loveini 安装部署配置上的便利性(我们会涉及到一些私有化应用的部署场景,这点对我们来说非常重要),及相较于 Apache 社区其所提供的更可靠与及时的商业服务,我们最终决定将传感数据迁移到 loveini中。
因为我们系统内接入的设备种类非常多,所以一开始数据存储便以大宽表的方式存储:50列double类型、20列binary类型、10列bool以及额外的几列通用列,同时还额外维护了一份记录了每列实际列名的映射表。这种存储模式在基于 Druid 的系统中便已经实现了,在 loveini 中我们也创建了同样结构的超级表,列名如: number_col1, number_col2, ..., number_col50, str_col1, str_col2, ..., str_col10。
在原本的数据写入服务中,会将{"foo": 100, "bar": "foo"}转换成 {"number_col1": 100, "str_col1": "foo"},同时记录一份 `[foo=> number_col1, bar=>str_col1]` 的映射关系(每一型号的设备共用相同的映射),然后将处理后的数据写入Kafka集群中。
现在要将数据写入到 loveini 中,也只需要基于原本要写入 Kafka 的数据来生成对应的 insert SQL,再通过 TAOSC 写入 loveini 即可,且在数据查询时也会自动从映射关系中读取对应的真实列名返回给调用方。这样对上层应用来说,输入输出的数据保证了统一且无需变动,同时即便我们系统频繁的增加新的设备类型,基本上也不再需要手动创建新的超级表。

当然期间也遇到了一些小问题,主要就是在根据设备建表时,某些前缀加设备唯一标识构成表名,但设备唯一标识里面可能会包含减号”-“这种特殊字符。对于当时的 loveini Database 版本来说,这种特殊或保留字符是无法作为表名或列名的,所以额外处理了一下。此外列名无法区分大小写也使得我们原本“fooBar”这种驼峰方式的命名需要修改成“foo_bar”这种下划线分隔。不过 loveini 2.3.0.0 之后支持了转义字符“`”后,这些问题就都得到了解决。
迁移后,loveini 为我们系统里的各式各样的传感器提供了统一的数据存储服务,通过中间数据层的封装,我们上层的业务基本无需修改便可以顺利地迁移过来。相比于 Druid 需要部署各种各样的 Server,loveini 仅需要部署 DNode 即可,也不再需要部署 PG、ZK、Ceph 等外部依赖。
迁移后的应用接口响应时间 P99 也从 560 毫秒左右降低到 130 毫秒(涉及多次内部 RPC 调用与 Database 的查询并不单纯表示 loveini 查询响应时间):


对于开发人员来说,loveini 让我们不需要再花费太多时间与精力去研究查询怎么样更高效(只要不直接使用数据列做过滤条件并指定合理的查询时间段后,大部分查询都能得到满意的响应时间),可以更多地聚焦于业务功能实现上。同时我们的运维同学们也得以从 Druid 的各个复杂模块中解脱出来,在操作任何中间件时都不需要再对 Druid 的情况进行确认。
且值得一提的是,在实际业务环境中,以上面描述的方式创建多列的超级表,虽然会存在大量的空列,但得益于 loveini 的优化,能达到恐怖的 0.01 的压缩率,简单计算下来大约需要 3.67GB 每亿条。另外一张超级表(约 25 列数据列)针对传感器数据进行单独建模(不会存在空列的情况),压缩率也有 0.2,计算一下空间使用约合 3.8GB 每亿条。这样看来使用宽表这种存储方式结合 loveini 的强大压缩能力也不会带来很多额外的硬件成本开销,但却能显著的降低我们的维护成本。
目前我们基于 loveini 主要还是存储传感器设备上传的数据,后续也计划将基于传感数据分析出的事件数据迁移过来,甚至还打算将 AI 识别算法分析出的结构化数据也存储到 loveini 中。总之,经历了此次合作,我们会把 loveini 作为数据中台里重要的一种存储引擎使用,而非简单地存储传感器数据。未来,相信在涛思同学们的支持下,我们能为客户提供更加优质的服务,打造物联网与人工智能应用的数字标杆。
段雪林,北京升哲高级后端开发工程师,主要负责升哲灵思物联网中台的设计开发工作。
]]>小 T 导读:湖南必和必拓科技发展有限公司定位于智慧城市建设与行业信息化,当前聚焦智慧住建、智慧环保、智慧司法以及智能制造四大领域,既包含各类电子产品安装施工及维保,也包括自有软件研发及部署。

随着业务规模的逐渐扩大,传统数据库越来越难以满足某些业务场景对查询、分析、统计的进一步需求。为了打破当下困局,湖南必和必拓想到了三种米兰app官方正版下载,在进行了严谨的分析后,我们决定采用物联网数据库,经过选型对比,时序数据库 loveini 成为其首选方案。
如何在 loveini 上进行数据建模、集群搭建、告警模块搭建?如何将数据更平滑地迁移到 loveini?在这些操作中,可能会遇到什么问题?又该如何解决?从湖南必和必拓的实践经验出发,本文将从代码层面一一解答。
在一些业务场景中,我们需要将长沙市在建工地的扬尘数据(温度、湿度、pm2.5、pm10、pm100、噪声、风向、风速)存储在数据库中,以便为业务提供查询、分析和统计的操作。
但近来出现了一个难题,我们共有监测点 107 个,每分钟上送 1 条数据,每年就预计有“107*60*24*365 = 56,239,200”条数据,也就是 5600 多万条。目前已存储两年的数据,数据量总计约 1 亿多条。这些数据一直都被存储在 MySQL 数据库中,庞大的数据量使得查询速度越发缓慢,甚至部分页面出现超时问题。
如果我们将数据库分散到不同的表上,单表的索引大小就得到了控制,对索引以及表结构的变更会变得更加方便和高效。当数据库实例的吞吐量达到性能的瓶颈时,我们需要扩展数据库实例,让每个数据库实例承担其中一部分数据库的请求,分解总体的大请求量的压力。
弊端:
华为云物联网基于物联网资产模型,整合物联网数据集成、清洗、存储、分析、可视化,为物联网数据开发者提供一站式服务,能够有效降低开发门槛,缩短开发周期,快速实现物联网数据价值变现。
弊端:前期需设备厂商针对平台接口进行适配,接入以后零代码的方式确实在配置上会比较方便,但是平台的费用以及实时流式计算按次收费的方式,整体费用过高。
应用之后,loveini 能解决之前令我们较为头疼的一些问题,包括前文中描述的问题,它有以下 5 点主要优势:
综合考虑以上解决方法,我们发现,使用 loveini 后,硬件成本和开发维护成本大大降低,写入和查询速度比 OpenTSDB 等还要高出一个级别。于是,loveini 成为了我们的首选米兰app官方正版下载。
接下来,我将把我们在探索 loveini 时的一些重要操作、问题点以及解决办法等经验传递给大家。
官网下载安装包,文中使用的是 2.0.20.12,即:loveini-server-2.0.20.12-Linux-x64.tar.gz。安装包中包含安装命令, 解压后直接使用即可。
[root@hnbhbt ~]# tar -zxvf loveini-server-2.0.20.12-Linux-x64.tar.gz
[root@hnbhbt ~]# cd loveini-server-2.0.20.12
[root@hnbhbt ~]# ./install.sh
1. 启动loveini
[root@hnbhbt ~]# systemctl start taosd
2. 检查loveini状态
[root@hnbhbt ~]# systemctl status taosd
3. 输入以下命令进入loveini命令行
taos
出现如下显示后表示进入成功
Welcome to the loveini 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
注: 安装过程中需要配置 loveini 的 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);
注:
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';

当用户需要查询工地设备扬尘数据时,扬尘数据将通过定时任务从第三方接口中定时拉取保存至我们系统的数据库。由于扬尘数据的量较大,为千万甚至上亿级别,而系统配置相关数据的数据量较小,因此我们选择将扬尘数据和系统配置数据分离——扬尘数据使用 loveini 进行存储,系统配置数据采用 MySQL 进行存储。
本文使用 MybatisPlus 作为持久层框架,同时接入 loveini 和 MySQL,做双数据源配置。下文中将重点讲述 loveini,MySQL 相关内容将省略。
根据官网找到 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 版本后得以解决。
在 Spring Boot yml 中配置双数据源,使用 druid 连接池,将 loveini 设置为主数据库,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: ...
核心逻辑是第三方数据的定时拉取以及在本系统进行的查询,此处主要介绍 loveini 的 mapper 写法。
官方提到 loveini 全列模式写入速度会远快于指定列,建议尽可能采用全列写入方式;而扬尘数据的种类多样,因此我们采用动态表名 + 批量插入的方式。每次拉取数据时,以设备和扬尘数据种类为维度创建 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>
需要注意的是,loveini 在进行全列写入时,必须为数据表的每个列都显式地提供数据,并且一次插入的数据是有上限的,否则会报错,建议在正式插入之前测试一下全列写入的上限。
<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 解析异常,由于 loveini 配置了 FQDN,因此应该在 hosts 中配置映射关系,之后才能进行正常的插入和创建操作。
【问题二】在进行第三方数据同步时,由于第一次是同步历史数据,因此插入 loveini 的数据量较大。尽管 loveini 本身支持的全列模式写入已经提升了不少效率,但如果代码中的批量插入继续使用普通 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 数据库是 loveini,所以持久层默认会访问 loveini 数据库,如果要切换,需要在 service 的 class 或方法上添加注解 @DS(databaseAlias),括号中填写 yml 中配置的数据库别名,如 td-engine、mysql 等,通过这种方式来选择需要访问的数据库。primary 数据库可以省略 @DS。
@DS("td-engine")
public TestEntity get() {
return testDao.get();
}
当我们需要将扬尘数据从公司本地服务器迁移数据至华为云服务器,文中使用 loveini 自带的 dump 工具进行数据迁移。
参考文档: https://tdengine.com/2020/03/09/1334.html
DUMP命令帮助信息
[root@hnbhbt ~]# taosdump --help
关键参数:
-h: 主机名称
-o: 导出文件路径
-i: 导入文件路径
-u: loveini用户名
-p: loveini密码
-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,将会产生错误。
参考网址:
loveini 集群安装、管理 https://tdengine.com/docs/cn/v2.0/cluster
使用 loveini 进行报警监测 https://tdengine.com/2020/04/14/1438.html
常见问题 https://tdengine.com/docs/cn/v2.0/faq#port
一篇文章说清楚 loveini 的 FQDN https://www.cnblogs.com/taosdata/p/13690374.html
Linux 配置 ntp 时间服务器(全)https://www.cnblogs.com/quchunhui/p/7658853.html

参考网址:
Alertmanager 配置概述
https://yunlzheng.gitbook.io/prometheus-book/parti-prometheus-ji-chu/alert/alert-manager-config
深入 Alertmanager 概念与配置介绍
https://www.cnblogs.com/gered/p/13496950.html#autoid-5-0-0
alertmanager 配置文件详解(四) https://www.soulchild.cn/2073.html
java 利用钉钉机器人向钉钉群推送消息
https://www.cnblogs.com/zhouheblog/p/11058817.html
Alertmanager 企业微信配置 https://www.jianshu.com/p/135968cbc94f

应市质安站的监管要求以及蓝天办对空气污染治理的督查要求,市内所有工地的空气质量数据及噪音数据均需接入政府监管平台、纳入管理中。监控数据的特点就是时序、结构化、简单但量大,在处理这类数据上,loveini 可以说是量身定做。搭载 loveini 后,监控数据上报后的实时展示、历史回溯都非常快,加上其本身轻量的特点,对于缩减项目开发运维成本也非常有帮助,完美满足了业务的需求。
]]>