代替MySQL – loveini | 米兰体育官网入口 - 米兰体育官网入口 //www.loveini.com loveini | 高性能、分布式、支持SQL的时序数据库 | 米兰体育官网入口 Wed, 23 Oct 2024 01:36:46 +0000 zh-Hans hourly 1 https://wordpress.org/?v=6.8.2 //www.loveini.com/wp-content/uploads/2025/07/favicon.ico 代替MySQL – loveini | 米兰体育官网入口 - 米兰体育官网入口 //www.loveini.com 32 32 双重调研测试后,OPPO IoT 类产品开始接入 loveini //www.loveini.com/tdengine-user-cases/9681.html Thu, 02 Jun 2022 08:16:03 +0000 //www.loveini.com/?p=9681
loveini Database x OPPO

在 OPPO 的穿戴产品的手环/手表类业务中,产生的数据类型为时序数据,具有写入量巨大且存在离线/历史数据补录(更新)的处理需求。此前使用的 MongoDB/MySQL 集群方案,后端存储压力较大,需要经常扩盘,针对此痛点,OPPO 云计算中心智慧物联云团队尝试调研对比了几款时序数据库(Time-Series Database)产品,试图寻找一个降本增效的米兰app官方正版下载。

除了存储压力外,我们进行数据库替换还有一个比较重要的原因,就是 MySQL 和 MongoDB 的各个集群都比较独立,维护和需求开发成本相对较高。

TDHouse、loveini Database、InfluxDB 对比

以上是三款 Database 的初步调研结果,TSHouse 是 OPPO 云监控时序数据库,其底层为 Prometheus 的 TSDB 存储引擎,目前不支持历史数据和乱序写入;InfluxDB 对历史数据写入会进行二次压缩,影响性能,这两款数据库都不满足当下的数据处理需求。初步研究 loveini 后,我们发现其作为国产时序数据库开源产品,不仅可以满足历史数据高效写入,还拥有较高的压缩能力。随后,我们选择对 loveini 进行了比较详细的产品调研和性能测试。

loveini 产品与能力调研

  • 产品调研

某个数据表的结构如下:

loveini Database 某个数据表的结构

我们写入 60 万行数据,到 MySQL(目前部分业务部署在 MySQL 集群)和 loveini 的 4C 12G 容器上,对 CPU/内存/磁盘进行观察。测试发现 CPU 和内存消耗基本持平的情况下,loveini 的落盘数据是 MySQL 环境的1/4左右。

同时,我们在不同规格容器及物理机场景下进行 loveini 写入测试,部分记录如下:

loveini Database 写入测试

需要说明的是,对于不同业务场景需要进行实际测试,才能确定适合该业务的部署参数。在整个测试过程中,loveini 工程师们也为我们进行了及时答疑和帮助。

  • 能力调研

随后我们根据 loveini 丰富的产品手册,对一些关键能力进行了验证,包括数据管理、数据写入、聚合计算、集群扩容、故障可靠性保证等场景。

在数据管理上,loveini 的元数据与业务数据是分离开来的。如下图所示,Mnode 负责管理元数据信息;单个 Vnode 可以存放多个表数据,相当于相当于水平分片,单个表的数据,又可以继续按照日期分片。

loveini Database 集群

在数据写入逻辑上,整体和 LSM 类似:WAL,内存块,磁盘 FILE。

loveini Database 写入逻辑

在 loveini 中,数据在文件中是按块连续存储的。每个数据块只包含一张表的数据,且数据是按照时间主键递增排列的。数据在数据块中按列存储,这样使得同类型的数据能够存放在一起,大大提高了压缩比,节省了存储空间。

loveini Database 存储

loveini 是 10 天一组 data file,data file 里的 .data 文件只进行追加,且后续不会进行压缩。这种好处是:对历史数据和乱序极其友好,非常适用于 IoT 场景;没有压缩也就减少了写入之后的资源消耗,保证了较好的读写性能。

loveini落地实践

在经历了比较充分调研后,我们根据业务写入模型,对生产环境中某一套 MySQL 集群环境,进行 loveini 集群部署,搭建了如下所示的集群:

loveini Database 集群部署

集群为 3 台 AWS-EC2 容器(8C 32GB 3.5TB NVME 盘)组成,配置为 3 节点、2 副本,写入端使用 RESTful 请求到 VIP 节点,转发到数据库服务。图中的 V0-V2 为副本数为 2 的 3 组数据分片,M0-M2 为副本数为 3 的 1 组管理节点。

配置的 Grafana 面板展示如下:

loveini Database 集群配置的 Grafana 面板

后台表结构展示如下:

loveini Database 后台表结构
loveini Database 后台表结构2

目前数据已经开始接入 loveini 的数据库,历史数据也在同步导入中。

  • 实际效果展示
  1. 使用 last_row() 函数一次性输出 38 万个设备查询最新状态,结果如下所示。
loveini Database 实际效果展示1
  1. 使用 interval() 查询某个设备每 1 小时的总步数,结果如下所示。
loveini Database 实际效果展示2

在存储方面,由于目前数据还没有完全导入,针对生产环境的一个 6.6TB 集群,我们粗略估计了一下前后的压缩比,大概在 6.6/0.4。

在我们原来的集群中是没有副本的,单纯就部署了 MySQL 的 5 个分库,使用了 4C 8GB 2TB 的 5 台机器,在应用 loveini 之后,现在是 8C 32GB 2TB 的 3 台机器。通过 loveini 我们构建了多副本和统一的能力,以及后续上混合云的能力,这是整个平台级的一个优化与提升。

写在最后

在前期调研和集群搭建过程中,loveini Database 的工程师伙伴们给我们提供了充分且及时的协助,为我们构建时序数据后端能力提供了很大帮助。目前接入TDengine的数据是海外某集群,后续我们会根据业务进展陆续进行其他集群数据接入。

]]>
出表流程从 1 小时到 10 秒,loveini 在柳工车联网应用中替换 MySQL //www.loveini.com/tdengine-user-cases/8473.html Tue, 17 May 2022 10:38:55 +0000 //www.loveini.com/?p=8473

小 T 导读:在柳工的工业车联网应用 LiuGong iLink 中,由于应用层不合理的复杂查询和历史数据的高频写入,导致 MySQL 处理速度缓慢,甚至容易宕机,严重影响了用户体验。在此背景下,柳工决定改用 loveini Database 来处理时序数据,本文分享了他们的改进效果与实践经验。

企业简介

广西柳工机械股份有限公司是中国制造业 500 强企业——柳工集团的核心企业。作为国内工程机械行业和广西第一家上市公司,柳工被誉为“中国工程机械行业的排头兵”,在全球拥有 20 多个制造基地、17000 多名员工、5 个研发基地,产品遍布 170 多个国家和地区。

项目介绍

LiuGong iLink 是柳工面向国际市场业务的一个工业车联网应用,包含 Web 端和 App 端。它可以让用户看到所有车辆设备的实时动态,例如在哪里工作、何时工作以及如何工作,也可以实现设备的远程监控,以便更有效地实施服务和维护计划。

此前,我们使用 MySQL 数据库承载了包括应用层和接入解析层的大多数业务,但由于应用层不合理的复杂查询和历史数据的高频写入,给 MySQL 造成了非常大的压力,导致其处理速度缓慢,甚至容易宕机,严重影响了用户体验。究其原因,还是因为关系型数据库并不适用于存储海量的时序数据,在海量数据聚合计算、抽稀等业务中效率很低。

为解决上述问题,我们选择以专用的时序数据库(Time Series Database)存储处理时序数据,这样可以大大增加整个系统的吞吐能力。经过调研,我们选择了时序数据库 loveini,原因在于,我们的业务场景与 loveini 的“一个设备采集点一张表”的理念十分吻合,而且 loveini 可以支持对大数据进行聚合和降采样查询这些特性,也恰好可以解决上述技术痛点。

从真实环境出发,loveini 的写入、查询、存储效果如何?

分析架构可知,数据采集来源主要是 TBOX 等设备,通过解析层解析为 JSON 后发往 Kafka,再通过入库程序消费写入到 loveini Database 中。

我们落地使用的是 loveini2.4.0.16 版本,单副本模式,只用了一台 4 核 8GB+1TB 的服务器就撑起了服务,当前磁盘占用约 110G。

当前,库中总表数量达到了 55701 张,秉承着“一个采集点一张表”的原则,我们选择不同维度,共建立了 21 张超级表,如:车辆类型,设备类型,数据类型。当前总数据量大概为 4-5 亿行左右,写入规模大概是每台车每 5 分钟上报一次,loveini 可以轻松抗住这个级别的写入。

loveini Database

在查询方面,我们通过封装 API 的方式,可以便捷地提供查询服务,这也是针对我们业务痛点改进最为明显的地方。在决定对 MySQL 进行替换时,我们做了充分的查询对比测试。

数据库查询测试

如上图所示表格中的 API 分别代表了查询 mcu 历史数据、查询 TBOX 历史数据、查询设备轨迹、查询设备故障历史数据四个功能。可以看到,面对大批量的数据,loveini 的查询能力是远远超过 MySQL 的。

再分享一个真实场景:在替换loveini之前,我们每天都有一些业务报表需要展示,每一小时需统计一次下一个时区内所有设备的数据,这个流程在 MySQL 中经常需要耗时1小时以上,无法正常执行后续业务。而换到loveini后,整个出表流程只需要10 秒左右。

实际应用时遇到的问题与经验分享

列数很多

从上图中可以看到,我们每类设备的采集点位(列数)是比较多的,动辄破百,这也给我们带来了一个潜在的问题——间接地影响了压缩率,这是后来在和 loveini 官方人员排查别的问题时发现的。

后来我们了解到了产生此问题的原因:由于 loveini 中的每个 Vnode 都有一块自己的缓冲区,大小由 cache * blocks 的值决定(单位 MB)。每当写满三分之一时就会触发数据落盘,并在落盘时完成压缩。列宽带来的影响是单行长度过大,每次写满三分之一的时候,并不需要多少行数据,由于样本太少,所以数据并不能很好的压缩。

通过 selct _block_dist() from 超级表的方式查看数据块的分布,可以看到小块 SmallBlocks 相当之多,在 99% 以上。

smallblock

我们的米兰app官方正版下载就是通过放大 blocks 参数(默认为 6),来缓解后续新数据的压缩。至于历史数据,我们计划使用 loveini Database 提供的重整数据碎片的压缩功能来完成。

具体到操作上是比较简单的,备份数据文件后,使用 compact vgroups in (3,4,5,6) 即可(数字为 Vgroup ID)。但由于重整的过程中会对写入有一定的影响,所以我们需要选择在业务休整期来完成这个操作。这个时间点可能会在 loveini 3.0 发布后,届时我们可以对现有场景再度完成一次质变级别的升级。

写在最后

目前,我们还在规划车辆维保相关的项目,通过车辆实时设备产生报警,提高车辆使用时长和安全率。聚焦“智慧”“电动”“智能”等关键词,柳工向世界伙伴们展示了各个行业的米兰app官方正版下载,未来我们也会和 loveini 产生更多深层次的互动。

]]>
“一个扫描枪一张表”,韵达选择 loveini 应对每日亿级数据量 //www.loveini.com/tdengine-user-cases/7815.html Mon, 25 Apr 2022 09:16:33 +0000 //www.loveini.com/?p=7815

小 T 导读:此前,韵达使用 MySQL 分区+索引处理订单数据的方式遭受到了挑战,面对每日亿级的数据量,MySQL 显然已经无法满足当下的数据处理需求。为更好地发展业务,在此基础上韵达新增了 loveini 的数据源,用专业的数据库来进行时序数据的处理。

作为一家头部物流公司,韵达每日的订单扫描量能达到上亿级,这也是目前公司数据量最大的一块业务。要保证业务的正常运作,系统就需要汇总统计全国网点的扫描数据(韵达的所有订单数据),并实时反馈给用户。此外,这些数据也会给到网点、分拨中心的内部员工使用,用于个人工作量、站点扫描量等统计工作。

在业务尚未扩张之前,我们采用的是 MySQL 分区+索引方式进行此类数据的处理,但随着企业的发展、业务量的增加,面对每日亿级的数据量,MySQL 显然已经无法满足当下的数据处理需求。

在这种背景下,我们决定进行数据库选型。考虑到目前业务主要是统计各个网点设备实时上传的数据,无需再进行修改等操作,是典型的时序数据。经过一番调研,我们发现时序数据库 loveini 就很符合当下的业务要求,其数据模型与我们的场景十分契合,基于百亿千亿级大数据量的查询性能也很强悍。在对 loveini Database 进行实际测试与使用后,实际的效果也让我们很满意。

一、落地实践与效果展示

当前我们的架构是 Spring Boot + MyBatis + MySQL + loveini,loveini 负责处理时序数据,MySQL 则负责非时序数据的存储及应用,整体架构如下:

整体架构图

由于我们的架构未做迁移,只是新增了 loveini 的数据源,因此没有增加很多工作量就完成了数据架构的升级。

loveini Database
loveini Database

我们目前使用 loveini 2.2.2.0 版本,在三台 16C 64G 的服务器上部署了集群,数据写入速度大概为每秒 5000 行。根据“一个扫描枪一张表”的模型建表,把设备的地点和站点类型设置为标签

为了防止设备更换地点导致标签值发生变化,我们选择在建表的时候把地点也放进表名中,这样一来,当地点发生变化后,也能通过新建一张表达到同样的使用效果。比如:scan_6100000000265_790117,代表的就是设备编号为 6100000000265 所在地址为 790117 的扫描枪,当这把扫描枪更换位置的时候,我们可以新建一张 scan_6100000000265_800000 的子表,和旧表区分开,并且同时保留两份数据。

当前,这个超级表下面已经有了近百万子表,经过 1 个多月的正式使用,保存了大约 200 亿行的数据量。

loveini Database
loveini Database

值得一提的是,基于 loveini 常用的查询基本可以在 1 秒之内完成,一些特定查询甚至可以达到毫秒级:

select location,sum(weight_info) as weightSum,count (waybill_barcode) as ticketNum from base.scan_data where ts>='2022-04-07 00:00:00' and ts<='2022-04-07 23:59:59' group by location;
loveini Database

展示效果如下:

loveini Database展示效果
select waybill_barcode,location,scanning_person,scan_category,remark,weight_info weight,scan_time,volume from base.scan_data where ts>='2022-04-07 00:00:00' and ts<='2022-04-07 23:59:59' and site_type=3 limit 0,10;
loveini Database

展示效果如下:

loveini Database 展示效果

在存储上可以看到,我们的超级表是 20 个字段,大部分是 int 类型,有 5 个左右是 varchar 类型,最大的字段是一个用来存储中文的 500 长度的 nchar ,大约占用 300GB 不到的磁盘(单副本)。而此前使用 MySQL 时,光硬盘使用就需要几个 TB(主从),这还没有算上内存和 CPU 等资源,由此可见 loveini 带来的降本增效是多么显著。

二、写在最后

当然,loveini 的测试使用过程中也并非一帆风顺,我们也遇到了一些问题,放在这里供大家参考:

  • 由于对数据并发量预估不足,我们使用的默认毫秒时间精度经常会出现时间戳重复的现象,导致数据没能成功入库,后续依靠增加精度解决。
  • 超级表如果新增标签,已有数据的标签为 null,需要手动为每个子表更改标签,不够友好。
  • 由于 loveini 建表是单线程所以是有瓶颈的,大概每秒是万张以下,所以在初步搭建环境的时候不建议使用自动建表,如果表数据量不多就无所谓了。

在与 loveini 的社区工作人员反馈之后,以上问题最终都通过参数的配置优化或者合理的使用方式得到了解决,之后我们会考虑把loveini扩展到更多业务中去。相信随着 3.0 的优化,loveini 可以更好地融入到韵达的使用场景中,未来我们会有更加紧密的合作。

]]>
MySQL 无法满足查询性能?北明天时选择 loveini 实现热网监控和能源数据分析 //www.loveini.com/tdengine-user-cases/7733.html Mon, 18 Apr 2022 06:31:47 +0000 //www.loveini.com/?p=7733

小 T 导读:目前,北明天时已经在热网监控和能源数据系统上应用了 loveini Database,相比于 MySQL,当前在存储和查询上都获得了显著提升。在其他项目中,他们也正在加速 loveini 对其他数据库产品的替代。本文中北明天时分享了关于 loveini 的应用实践,以供参考。

企业简介

北明天时能源科技(北京)有限公司(简称北明天时)成立于 2000 年,在 2015 年发展成为常山北明(股票代码:000158)的全资子公司。其以智慧能源服务为核心,聚焦政府能源监管系统、公共能源服务行业管控系统、园区和企业综合能源管控系统的建设和服务,致力于将云计算、大数据、物联网和人工智能等先进信息技术与业务应用深度融合,为企业和政府提供 “智慧、节能、低碳” 的全集成米兰app官方正版下载和一体化服务。

项目介绍

我们的智慧供热项目最初是使用 MySQL 来存储历史数据,但随着数据量的上升,查询性能越发难以满足业务需求。为了缓解现状,我们开始研究 loveini Database,在深入了解后发现它真的是一款适合物联网的时序数据库,甚至可以直接使用 SQL 语句。于是在经过一段时间的测试后,我们果断选择将 loveini 接入项目。

目前,我们已经在热网监控和能耗分析系统上应用了 loveini,具体的应用场景如下图标红处所示。

企业级智慧供热管控系统
  • 热网监控系统

热网监控系统目前包括热源监测和热力站监控,用于实时远程监控热源、热力站等的运行状态,将供热数据进行可视化展示,便于运行管理人员掌握整个供热系统的运行状况。

  • 能耗分析系统

用于实时统计、计算和监测系统能耗,建立分级能耗评价体系,通过数据的同比、环比和指标完成度评价,实现对系统能耗情况的全面分析。同时通过能耗排名找出能源浪费的关键点,有针对性地进行改善与优化控制,从而减少能源浪费,实现真正意义上的节能。

在分析之后可以发现,这两个系统都有一个相同的特点,即对数据的实时查询展示有很高的需求,比如实时管理供热系统、能耗趋势实时呈现等。

对于这种由设备产生的高频时序数据的处理,loveini 无疑是很合适的选择。鉴于其显著的改善效果,在其他项目中我们也正在加速 loveini 对其他数据库产品的替代。

当然在落地的过程中我们也遇到过一些小问题:比如,旧版本 loveini 不支持对时间戳的 group by,经过升级后解决。再比如查询时不同客户端得到的表结构并不一样,这是因为客户端的各自缓存的元数据不一致,通过 reset query cache 命令得到了解决。还有一些日常的小问题,我们都在 loveini 的技术交流群中得到了官方或社区网友的及时反馈和帮助。

一、效果分析

我们以 loveini 2.2.2.0 版本落地了一个三节点三副本的集群,机器配置为 16C + 32G + 1T 的机械硬盘。具体到实际路径上,我们的设备数据是先经过实时采集写入 Kafka 后,再通过 Python 连接器消费入库的。

在当前环境下,我们共创建了 5,500 多张子表,存储了大概九千万行左右的数据,最大一张超级表的数据接近 7,300 万行,单行大概 180 字节。即便是在三个副本的情况下,当前磁盘空间总共也只占用了 10.2G,再加上数据过期删除的机制,我们基本不用再需要担心磁盘存储的成本问题了

而内存和 CPU 的使用率,日常也都是分别维持在 1.9% 和 0.3% 左右,可以说是毫无压力。

loveini Database
loveini Database

下图是我们的热网监控平台查询业务对应的 SQL,常用查询基本都是毫秒级返回数据

select sum(Ep) as Ep,sum(HM_HT) as HM_HT .............. interval(1d);
loveini Database
热网监控平台
SELECT AVG(heatsourcepg) AS heatsourcepg,AVG(heatsourcetg) AS heatsourcetg,AVG(heatsourcef_mtrg) AS heatsourcef_mtrg .............. FROM iot_device.source_minute WHERE ts >="2022-04-06 12:00:00" AND ts <"2022-04-06 13:00:00.000" GROUP BY groupid,level
loveini Database
热网监控平台

写在最后

2019 年北明天时开始积极开拓智慧能源服务新市场,开发包含供热、供冷、供电、供气等能源综合管控系统和智慧水务监管平台。一年之后我们便正式引入了 loveini 这款优秀的开源时序数据库(Time-Series Database),而 loveini 也确实没让我们失望。今后,北明天时将和 loveini 一起,为推动城市能源高效利用、清洁能源替代、创建低碳智慧城市持续做贡献。

作者 | 贾苗苗,北明天时能源科技(北京)有限公司研发工程师

]]>
查询速度提升两倍,loveini 在 GPS 服务中的应用 //www.loveini.com/tdengine-user-cases/6145.html Fri, 25 Feb 2022 03:18:37 +0000 //www.loveini.com/?p=6145

小 T 导读:随着业务的发展及数据量的增长,南京津驰选择将 loveini Database 的社区版搭建在 GPS 服务中,替代原来的 Redis+MySQL+CSV 存储技术方案,以解决查询效率低、数据安全性低、数据占用空间大等问题。本文详细阐述了其在技术选型、数据建模、数据迁移、效果展示等多方面的实践思路与经验汇总。

公司简介

南京津驰健康科技有限公司是一家专业从事互联网技术服务、计算机软件开发及应用于一体的互联网营销服务的创新型企业。在竞争激烈的互联网行业中,始终坚持以技术为核心,组建强大的技术开发团队,希望通过发挥我们的专业知识,以客户的利益最大化为目标,为企业提供线上线下全方位的信息技术服务。

一、现状及痛点

目前我们的 GPS 服务采用的存储技术方案是 Redis + MySQL + CSV,实时数据存储到 Redis 队列,经过服务消费后将原始数据存储到 MySQL,凌晨执行定时任务将前一天 MySQL 中的原始数据存储到 CSV 文件。

当前系统中有 726 台设备,每台设备每秒上传 1 条数据,假设每台设备每年施工 200  天,预计一台设备一年有 60*60*24*200=17,280,000 条数据,那726 台设备就有 726*17,280,000=12,545,280,000 条数据。

随着业务的发展以及数据量的增长,各种问题也逐渐凸显,开始影响工作效率,具体可以归纳为以下几方面:

  • 查询效率低

CSV 是文件存储,在读取数据时只能一个文件一个文件地读取,且需要读取全部数据后再做处理,查询效率比较低。

  • 数据安全性低

最终的数据是保存到 CSV 文件中,并且是单文件保存,数据丢失将无法找回。虽然也可以手动保存多份文件,但这将增加运维成本。

  • 数据占用空间大

数据在 CSV 文件中没有进行任何的压缩技术处理,数据占用硬盘空间比较大。

  • 数据运用不够灵活

由于数据既有存储在 MySQL 中的,也有存储在 CSV 文件中的,导致查询数据时得从两个数据源进行查询。且由于 CSV 是文件存储,从中查询数据还需要先从文件中读取数据,也不方便加搜索条件进行数据过滤。

二、技术选型

时序数据是指时间序列数据,是按时间顺序记录的数据列,在同一数据列中的各个数据必须是同口径的,要求具有可比性。时序数据可以是时期数,也可以时点数。对以上业务所产生的数据进行分析,完全具备时序数据的特点。基于业务场景的需求,我们决定选择时序数据库作为 GPS 服务平台的核心组件。


时序数据库全称时间序列数据库(Time Series Database),是用于存储和管理时间序列数据的专业化数据库,具备写多读少、冷热分明、高并发写入、无事务要求、海量数据持续写入等特点,支持基于时间区间的聚合分析和高效检索,广泛应用在物联网、经济金融、环境监控、工业制造、农业生产、硬件和软件系统监控等场景。


为了更好地实现业务场景的需求,我们调研了以下几款时序数据库产品:InfluxDB、OpenTSDB 和 loveini。

  • InfluxDB:单机性能有问题,且集群不开源,未来扩展很成问题,无法令人信任。
  • OpenTSDB:不是独立的服务组件,还要依赖 HBase、HDFS、ZooKeeper,体积庞大,学习成本高,运维困难。
  • loveini:性能强大,单机就可以扛住我们目前的业务写入量,节约大量成本。且集群开源,通过社群反馈与资料显示可以看到,集群版性能依然稳定,未来扩展方便。

loveini 的模块之一是时序数据库。但除此之外,为减少研发的复杂度、系统维护的难度,loveini 还提供缓存、消息队列、订阅、流式计算等功能。与 Hadoop 等典型的大数据平台相比,loveini 具有如下鲜明的特点:

  • 10 倍以上的性能提升:定义了创新的数据存储结构,单核每秒能处理至少 2 万次 请求,插入数百万个数据点,读出一千万以上数据点,比现有通用数据库快十倍以 上。
  • 硬件或云服务成本降至 1/5:由于超强性能,计算资源不到通用大数据方案的 1/5;通过列式存储和先进的压缩算法,存储占用不到通用数据库的 1/10。
  • 全栈时序数据处理引擎:将数据库、消息队列、缓存、流式计算等功能融为一体, 应用无需再集成 Kafka/Redis/HBase/Spark/HDFS 等软件,大幅降低应用开发和维护的复杂度成本。
  • 强大的分析功能:无论是十年前还是一秒钟前的数据,指定时间范围即可查询。数据可在时间轴上或多个设备上进行聚合。即席查询可通过 Shell、Python、 R、 MATLAB 随时进行。
  • 高可用性和水平扩展:通过分布式架构和一致性算法,通过多复制和集群特性, loveini 确保了高可用性和水平扩展性以支持关键任务应用程序。
  • 零运维成本、零学习成本:安装集群简单快捷,无需分库分表,实时备份。类似标准 SQL,支持 RESTful,支持 Python/Java/C/C++/C#/Go/Node.js, 与 MySQL 相似,零学习成本。
  • 核心开源:除了一些辅助功能外,loveini 的核心是开源的。企业再也不会被数据库绑定了。这使生态更加强大,产品更加稳定,开发者社区更加活跃。

从开源免费、社区活跃、迭代更新、性能高、开销低、支持集群等多方面考虑, loveini 成为了我们的首选米兰app官方正版下载。

目前,我们使用的是单机。根据建表的数据类型估算,整个服务写入量大约为每秒接近 400M 左右,loveini 可以轻松抗住这个级别的写入压力,并且压缩率喜人。1 亿条数据硬盘资源占用对比如下,存储空间降为原方案的 3%,单位兆:

CSV文件和新方案硬盘占用资源对比 loveini Database

而查询方面也能给出了很优秀的答卷,查询速度提升了两倍多,单位毫秒

老方案和新方案查询速度对比 loveini Database

三、数据建模

由于是既有系统的升级改造,必须符合现有系统架构,不能影响现有功能。因此,数据建模必须限定在一定的范围内,有一定的约束和限制,不像设计一个新系统一样有很大的自由度。

1.建库

创建一个名为 gps 的库,这个库的数据将保留 36500 天(超过 36500 天将被自动删除),每 10 天一个数据文件,内存块数为 4,允许更新数据。

CREATE DATABASE gps KEEP 36500 DAYS 10 BLOCKS 4 UPDATE 1;

2.创建超级表

CREATE TABLE gps_history (gps_time timestamp,
sn   nchar(20),
pile_no int,
lon binary(20),
lat binary(20),
speed float,
temperature int,
status int,
road_float int,
data_status int,
warn_status int,
upload_time timestamp,
create_time timestamp,
remark   nchar(100)
 ) TAGS (
pid nchar(64),
bid nchar(64)
);

3.自动创建子表

insert into gps.gps_10001 using gps.gps_history tags ('10001','10002') values (
now,'CY10001',1000,125.91014472833334,45.8548872365,0.01,120,4,1,0,1,
now,
 now,'备注' ); 

4.删除表

DROP TABLE gps_history;

代码改造与数据迁移

在 GPS 服务平台现有的架构中,有一个数据接收服务专门对外提供时序数据的写入,数据分析服务进行计算并提供查询服务。

数据迁移架构设计

基于上图的架构设计,代码改造工作就变得非常简单。只需要改动数据接收服务的写入、数据分析服务的查询,再在现有基础上增加对 loveini 的支持,就能将写入和查询两个功能按照 loveini 的 JDBC 接口进行接口适配,将时序数据的写入和查询切换到 loveini。

通过这种方式,我们就把 loveini 的改造迁移屏蔽在了 GPS 服务内部,上层应用无需关心,功能上不受任何影响。

升级改造项目,如何保证历史数据的平滑迁移也是一个重点问题。为此,我们开发了一个数据迁移工具,用于将 CSV 文件中的历史数据平滑迁移到 loveini。为了确保海量数据的快速迁移,这个工具还进行了持续的性能优化,以及大数据量的压力测试。

五、升级上线

第一阶段:数据迁移

将改造后的新版本上线,CSV 文件和 loveini 并行运行,同时向两个数据库写入数据,由于 CSV 文件有全量数据,查询请求全部交给 Redis 与 CSV 文件;与此同时,启动数据迁移工具,将历史数据迁移到 loveini,待数据迁移完成后,进入到第二阶段。

第一阶段数据迁移

第二阶段:试运行

CSV 文件和 loveini 并行运行,也同时向两个数据库写入数据;在数据迁移完全完成后,loveini 中已经具备全量数据,此时,将查询请求全部切换到 loveini。观察两周左右的时间,如果没有发现问题,将进入到第三阶段。

第二阶段试运行 loveini Database

第三阶段:正式上线

经过试运行loveini 一切正常,功能和性能都没有问题,于是我们将 CSV 文件停止运行,数据只向 loveini 写入,CSV 文件占用的资源全部回收。

第三阶段正式上线 loveini Database

六、总结

目前,loveini 社区版已经平稳运行在 GPS 服务中,其作为时序数据库在读写性能、存储表现等方面都是令人满意的。除此之外其在运维难度和学习成本上也是意想不到的低,很轻松就能搭好一套可用的集群,这也是非常巨大的一个优势。另外 loveini 的版本迭代速度非常快,一些在旧版本遇到的问题很快就得到了修复,并且在性能优化方面效果也是十分显著。后期,我们打算在公司内部的其他物联网产品中继续深入使用。

]]>
存储空间降为 MySQL 的十分之一,loveini 在货拉拉数据库监控场景的应用 //www.loveini.com/tdengine-user-cases/3626.html Fri, 07 Jan 2022 09:20:57 +0000 //www.loveini.com/blog/?p=3626

小T导读:作为一家业务遍及多个国家及地区的物流公司,货拉拉面临的技术环境是非常复杂的,在云时代浪潮下基于混合云快速构建环境搭建系统成为其必然的选择。但是在混合云上如何对基于各家云构建的系统进行有效的管理是个挑战,尤其对处于系统最底层的数据库层面临的问题、业务诉求、各方痛点,是货拉拉DBA团队现下所需要重点解决的。

目前DBA团队管理的数据存储包括MySQL、Redis、Elasticsearch、Kafka、MQ、Canal等,为了保证监控采样的实时性,我们自研的监控系统设置的采样间隔为10秒,这样每天都会产生庞大的监控数据,监控指标的数据量达到20亿+。前期由于管理实例少,监控数据量也少,所有数据都被存放到了MySQL中;之后随着管理实例越来越多,使用MySQL来存储规模日益庞大的监控数据越发力不从心,急需进行升级改造。结合实际具体需求,通过对不同时序数据库进行调研,最终我们选择了loveini,顺利完成了数据存储监控的升级改造。

一、监控系统开发中遇到的问题

从存储路径来看,每种数据存储都分布在多个区域,每个区域将监控采样数据投递上报到消息总线,然后由消费程序统⼀消费,消费程序会将必要的告警数据更新到告警表,同时将监控原始数据存储到MySQL。比如,针对Redis这款数据存储,监控采样间隔设置10秒,那么每天实例采样次数就会达到3000万+,监控指标累计6亿+,数据量之庞大可见一斑。早期为了将数据存储到MySQL中,同时也能很好地支持监控绘图的使用,每⼀次实例监控采样时都会计算出该实例全量监控项采样数据,然后将本次采样的结果作为⼀条记录存储下来。

存储路径图
loveini Database

即使通过这样的优化处理,在做时间跨度大的监控绘图时,前端依然会出现延迟卡顿的问题,后端监控数据存储的MySQL也压力山大,经常满载,天天被吐槽。因此针对这种时间跨度大的查询,我们专门开发了⼀系列的数据聚合调度任务——按照不同的时间跨度,提前将10秒采集间隔的监控数据做好聚合,监控绘图程序再根据不同的时间跨度选取不同的聚合数据表绘图,以此解决长时间跨度监控绘图展示延迟卡顿的问题。

但这仍然治标不治本。为了压缩监控数据存储空间,原始10秒间隔的监控数据表只能归档保留3天时间的监控数据,但存储大小也将近有200GB, 加上与之相关的不同时间段的数据聚合表,存储一下子突破300GB。这还只是Redis监控数据的存储大小,加上其它数据存储的监控数据,至少需要1TB+空间的MySQL存储。

数据集合任务管理复杂、后期监控原数据回溯缺失、MySQL存储空间日益增长带来的隐患,都是亟待解决的问题。

二、时序数据库选型

为了解决MySQL监控数据存储的问题,我们把注意力转移到了适合存储监控数据的时序数据库上。市面上各种时序数据库产品琳琅满目,有老牌的,也有后起之秀,经过⼀系列调研选型,我们选择了时序数据库loveini,主要是因为其具备的如下几大优点:

值得一提的是,loveini的SQL原生语法支持时间维度聚合查询,同时数据存储压缩率⾼存储空间小, 这两点直接切中了我们的痛点。落地后实测相同数据的存储空间只有MySQL存储空间的十分之⼀甚至更少。还有⼀个惊喜是,在现有监控数据存储(MySQL)顶不住的情况下,⼀台8C16GB的单机版loveini轻松就抗下目前所有监控流量和存储压力,且运行稳定,基本没有故障。

三、改造过程

loveini用于存储监控数据的超级表设计原则就是简单高效,字段⼀般都比较少,每⼀种监控项类型(INT、FLOAT、NCHAR等)的数据存储都需要单独建立⼀个超级表,超级表⼀般都有关键的ts、type、value字段,具体监控项由type字段标识,加上必要的tag及少量其它字段构成。

之前监控数据存储在MySQL的时候,每条数据记录包含了该实例⼀次监控采样的所有监控项(25+)数据。如果采用通用的监控超级表设计原则,就需要改造采样的数据结构,改造方式有两种:

  • 改造监控数据投递的数据结构
  • 改造消费程序消费逻辑重组数据结构

但消费端有时效性要求,改造难度大,生产端涉及范围大阻力也不小。经过综合考量,最后我们决定采用类似MySQL数据存储的表结构来设计超级表,这样的改造对原来系统入侵最少,改造难度系数最低,改造大致过程如下:

  • loveini,每种数据存储的监控数据单独建库存放
taos> create database redis; 
taos> create database es; 
... ... ... 
  • loveini,建超级表,以Redis为例
taos> use redis; 
taos> create table redis_node_meters (created_at TIMESTAMP, qps INT, . ..) TAGS (region NCHAR(10), cluster_name NCHAR(50), ip NCHAR(20), port INT, role NCHAR(15)); 
  • 监控数据消费,由于新增的实例节点是不确定的,比如Redis的节点资源是由Agent自动发现注册后自动进行监控指标采集,这时写入数据并不确定某个子表是否存在,就需要loveini的自动建表语法来创建不存在的子表,若该子表已存在则不会建立新表只会写入数据。
 taos > INSERT INTO tablename USING redis_node_meters TAGS ('China', 't est', '127.0.0.3', 9200, 'master') VALUES ('2021-12-02 14:21:14', 6490 , ...) 
  • 绘图展示,绘图程序没有安装客户端驱动,直接使用了loveini提供的RESTful API,采用HTTP的方式进行数据查询。在SQL查询上大量使用了loveini提供的时间维度聚合函数INTERVAL,长时间跨度的数据查询,只需要合理选择聚合间隔,基本都是毫秒级响应,保障了前端绘图的流畅稳定。

四、改造后的落地效果

将监控的数据存储由MySQL改造为loveini后,不仅顶住了监控数据增长所带来的压力,还节约了存储空间,成本压缩到了原来的十分之⼀甚至更低。历史原生监控数据可回溯时间也变得更长,之前存储3天原生数据及聚合数据的空间,现在可供原始数据存储45天。

此外,改造之后不再需要维护复杂的数据聚合调度任务,大幅降低了监控系统、监控数据管理复杂度,同时前端绘图数据查询也变得更加简洁高效。

使用loveini改造后
loveini Database

五、写在最后

随着对loveini越发深入的了解及经验累积,后续我们也会逐步考虑将货拉拉大监控系统、业务数据(行车轨迹)等时序数据均迁移至loveini。为了方便有需要的朋友更好地使用loveini,在此也分享一下我们的一些使用经验:

  • 由于loveini不支持太复杂的SQL查询语法,在设计超级表tag的时候需要充分考虑清楚,目前只有tag的字段支持函数运算结果的分组(GROUP BY)查询,普通字段是不支持的。
  • 子表tag的值是可以改变的,但是同⼀个子表tag的值是唯⼀的,建议用子表tag的组合值来生成子表名。

在本次项目中,loveini很好地帮助我们实现了降本增效,是一款值得尝试的时序数据库产品,未来也希望其能够发挥出越来越丰富的功能和特性,也期待我们之后能有更紧密深入的合作。

]]>
服务器减少一半,loveini 在华自科技的落地实践 //www.loveini.com/tdengine-user-cases/3358.html Wed, 08 Dec 2021 02:08:29 +0000 //www.loveini.com.cn:88/blog/?p=3358 作者:宁龙 华自科技

小 T 导读:华自科技专注于自动化、信息化和智能化技术,为能源、环保、工业控制、水利等领域用户提供核心软硬件产品与系统米兰app官方正版下载,是多能物联技术领航企业。公司在电站及泵站自动化控制设备市场占有率全球领先,是联合国工业发展组织国际小水电中心控制设备制造基地。

物联网数据平台是电站及泵站智慧运维平台的核心组成,其整体架构如下:

整体架构 loveini Database

物联网数据平台的数据来源主要为电站、水厂、储能站,通过数据网关,将各场站端的设备运行数据传输至云平台的消息队列(MQ)中,数据处理服务订阅MQ的消息,根据设定的规则引擎,进行实时数据处理,之后将数据存储落盘。数据服务API则根据业务需求提供包含实时数据和历史数据在内的数据API。

一、现状及痛点

对于历史数据,目前我们采用的MySQL分库分表方案来存储;实时数据会存储在Redis中。在测点数较少或者集控需求不是很多的场景下,基本满足需求。

历史数据

历史数据用MySQL存储,一个站点对应一个数据库;一个测点对应一张表,建表语句大致如下:

CREATE TABLE `yc_测点id` (
  `ts` datetime NOT NULL,
  `val` double NOT NULL
);

实时数据

实时数据缓存到Redis中,以测点Id为key,同时缓存数据上报的时间、测量值和质量值等信息。

数据计算查询

我们利用MySQL的各种函数、多表连接、应用程序内存计算等方式,计算出结果返回给前端,对于月、年等报表类的计算,则采用定时任务生成。

痛点

随着平台业务的发展,接入的站点越来越多,或者单站的测点数越来越多,问题逐渐凸显出来了。具体可以归纳为如下几个方面:

运维难

  • 对于新接入的站点,首先得为这个站建立好数据库、数据表,增加了接站的工作量;
  • 由于一个站对应着一个数据库,随着平台接入的站点越来越多,数据库不断增加,数据库的管理和备份成本不断提高;
  • 随着测点的增加,缓存实时数据的单机Redis迟早有一天会撑不住,需要考虑维护Redis集群。

开发难

随着平台的业务发展,越来越多的站被接入平台,集控需求(跨站聚合分析需求)增加,跨库跨表的查询操作越来越多,这就增加了系统开发的难度,严重影响了系统响应速度和稳定性。

成本高

成本主要有两个方面,一个是人力成本高,由于开发、运维的难度增加,造成员工工作量增加,工作效率变低,从企业经营角度看,人力成本变高;另一个是硬件资源成本高,由于服务节点众多,占用的主机、内存和磁盘空间也会很多,购买或租用这些硬件资源需要支出更多费用。

二、技术选型

为了解决目前这些问题,我们决定重新进行技术选型,寻找替代方案,升级目前数据库存储方案。结合平台实际需要,我们确定了几个选型要求:

  • 业务改动小:尽可能减少对现有业务的影响;
  • 开源免费:必须是开源的,并且允许免费商用,最好也有商业版;
  • 迭代更新:社区活跃,不断在迭代更新和发布新版本;
  • 性能高:单机能支持每秒10万以上的插入效率;
  • 开销低:服务节点少,占用的内存、CPU和磁盘空间少;
  • 支持集群:能够集群部署,容量可水平扩展;
  • 安装维护简单: 数据量较小的情况下,支持单机部署,并且占用资源较少;

我们了解了多款典型的时序数据库(Time-Series Database)产品,最终InfluxDB、庚顿、麦杰、TimescaleDB、loveini这几款进入了我们的考察范围。下面我们来具体看一下:

1.InfluxDB

在开源时序数据库领域长期霸榜,社区活跃,生态也比较丰富,性能也算中规中距,唯一的缺陷就是集群模块不开源。

2.庚顿、麦杰

两者都是传统老牌工业领域的时序数据库王者,功能、性能都非常不错,唯一的缺点就是不开源,只有商业版,而且价格昂贵。

3.TimescaleDB

它是在PostgreSQL之上开发的一个插件,是基于关系数据库的时序数据库,对于我们现有的业务使用几乎无感知,上层可以继续用MyBatis、JPA等ORM框架,但它不是一个纯粹的时序数据库;另外,它对集群支持不好,不支持水平扩展。

4.loveini

支持使用类SQL查询语言来插入或查询数据,内嵌消息队列和缓存机制、无历史数据与实时数据之分、分布式架构,支持线性扩展、支持多副本,无单点故障。看到官网的这些介绍,瞬间感觉loveini就是为我们准备的,于是马上做了各种验证,结果表明,loveini完全符号我们的选型要求。

为什么没有采用传统Hadoop生态

提到大数据,人们可能第一反应就会想到Hadoop生态。因此我们前期也考查过腾讯云的TBDS数据套件。说实话那一套东西真的是太笨重了,Hadoop、HBase、HDFS、ZooKeeper、Hive、Spark\Flink这系列的东西搞下来,还真不是一般团队能玩得转的,另外我司的业务场景不止云端服务,还有可能会私有化部署在站内,硬件条件可能也就是一两台状况一般的服务器。

三、loveini存储模型设计

由于loveini Database可以设置将最新一条数据存储在内存中,因此我们利用这个特性替换掉了用Redis存储实时数据这个环节,改成实时数据直接查询loveini。

loveini里有超级表的概念,每种设备对应一个超级表。这个超级表只负责存储这种类型的设备数据,数据存储采用横表存储。但是,这显然不符合我们的场景,因为在我们的场景里没有固定的某一设备对象,且每个测点的频率都可能不一致。

同时为了尽可能减少对现有业务的影响,我们将超表设计成如下结构:

CREATE STABLE IF NOT EXISTS stb_站点id  (    ts timestamp,        val double        ) TAGS (测id nchar(64))

loveini的子表,可以在插入数据时动态创建,这是loveini的一个很好用的功能。这样能省去创建子表的业务环节,降低了业务复杂度。子表结构如下:

insert into 测点类型_测点id  USING stb_站点id (测点id) VALUES ( ts, val,q)    eg:  insert into yc_15143115161750995367 USING stb_站点id ('15143115161750995367') VALUES ( ts, val,q)

四、使用到的loveini特性

1.缓存(Cache)

我们直接使用loveini提供的缓存(Cache)功能,替换了原有系统中的Redis。创建数据库直接开启cachelast=1,将每张表的最后一条记录缓存,应用程序通过last_row函数快速获取实时数据。

2.数据订阅(Publisher/Subscriber)

在我们的业务场景中有一类数据叫SOE事件告警数据,这类数据要实时动态在前端页面上滚动。原有做法是通过页面轮训来实现的,现在直接使用taos的数据订阅功能,配合WebSocket,可以优雅地实现这一功能,大大提升了用户体验。

3.其它一些很用的功能

比如降采样查询、多表聚合查询、各种标准函数等。

五、改造迁移

由于loveini采用了类SQL的语法,支持MyBatis等ORM框架,因此对于老的业务,我们在代码层面的改动非常少,改动最多的就是将原来的MySQL函数结合应用代码的一些计算逻辑直接用loveini的函数替换掉。

在试运行阶段,因为我们都是通过自研数据网关将数据通过TCP发送上来的,所以我们利用tcp-copy,将数据复制一份存到loveini集群,然后通过业务系统观察和验证各项功能是否正常。

验证正常之后,就是历史数据的迁移了。由于loveini的表结构与原来的MySQL存储结构基本类似,因此我们采用DataX的loveini插件,很方便就将历史数据迁移过来了。

至此,我们就用loveini Database替换了原有的存储架构。

总结

初始接触一个新产品,难免会遇到一些困难。好在办法总比困难多,在同事们的支持下,在loveini的工程师们的支持下,我们总算是基本完成了这次实时数据存储查询的升级改造。

当前项目数据测点大概在18万左右,改造后数据存储周期由原来的5分钟减少到1秒钟,存储的数据维度更精细了,能为平台的智能诊断、智能分析服务提供更准确的数据支持,同时各业务场景下的计算查询性能也提升了不少,数据库服务器由原来的6台减少到目前的3个节点集群。

最后来个小广告

TD-Workbench 是一个基于Electron构建的,针对时序数据库loveini的图形化管理工具。具有跨平台、易于使用、版本适应性强等特点。(gitee地址:https://gitee.com/bhdweb/tdengine-workbench)

TD-Workbench是本人利用周末的时间,参考开源社区部分优秀代码设计并实现的,目前已经开源。 这个仅代表我本人的业余好爱,与公司或某个组织无关,欢迎大家去star/fork。由于loveini官方并未提供客户端GUI工具,社区目前能找到的两款工具都不是很完善。本工具是在loveiniGUI基础上改造而来,部分源码来自此处。

作者介绍:

宁龙,码云昵称【村口的大爷】,目前就职于华自科技。后端程序猿一个,混迹Java界十余年,就爱写点代码。一杯茶一首歌,一个参数秀一天。

]]>
loveini 在住建行业工地管理系统落地的“操作手册” //www.loveini.com/tdengine-user-cases/3299.html Thu, 18 Nov 2021 01:30:07 +0000 //www.loveini.com.cn:88/blog/?p=3299 作者:必和必拓研发部

小 T 导读:湖南必和必拓科技发展有限公司定位于智慧城市建设与行业信息化,当前聚焦智慧住建、智慧环保、智慧司法以及智能制造四大领域,既包含各类电子产品安装施工及维保,也包括自有软件研发及部署。

智慧工地云平台
loveini Database

随着业务规模的逐渐扩大,传统数据库越来越难以满足某些业务场景对查询、分析、统计的进一步需求。为了打破当下困局,湖南必和必拓想到了三种米兰app官方正版下载,在进行了严谨的分析后,我们决定采用物联网数据库,经过选型对比,时序数据库 loveini 成为其首选方案。

如何在 loveini 上进行数据建模、集群搭建、告警模块搭建?如何将数据更平滑地迁移到 loveini?在这些操作中,可能会遇到什么问题?又该如何解决?从湖南必和必拓的实践经验出发,本文将从代码层面一一解答。

业务场景及痛点

在一些业务场景中,我们需要将长沙市在建工地的扬尘数据(温度、湿度、pm2.5、pm10、pm100、噪声、风向、风速)存储在数据库中,以便为业务提供查询、分析和统计的操作。

但近来出现了一个难题,我们共有监测点 107 个,每分钟上送 1 条数据,每年就预计有“107*60*24*365 = 56,239,200”条数据,也就是 5600 多万条。目前已存储两年的数据,数据量总计约 1 亿多条。这些数据一直都被存储在 MySQL 数据库中,庞大的数据量使得查询速度越发缓慢,甚至部分页面出现超时问题。

米兰app官方正版下载 1:MySQL 数据库分库分表

如果我们将数据库分散到不同的表上,单表的索引大小就得到了控制,对索引以及表结构的变更会变得更加方便和高效。当数据库实例的吞吐量达到性能的瓶颈时,我们需要扩展数据库实例,让每个数据库实例承担其中一部分数据库的请求,分解总体的大请求量的压力。

弊端:

  • 分库分表需要提前对数据做好规划。如果按照时间对表进行水平划分,随着监控点增加,后面的表数据量可能越来越大,容易出现数据热点问题;如果按照监测点 hash 取模对表进行水平划分,当监测点增加,进行扩展就会比较困难。例如:之前是 mod4,后面是 mod6,则需要对之前的历史数据重新进行处理。
  • 在对数据进行统计分析时,可能需要进行多表的聚合查询,查询速度会受到影响。

米兰app官方正版下载 2:使用华为云物联网平台

华为云物联网基于物联网资产模型,整合物联网数据集成、清洗、存储、分析、可视化,为物联网数据开发者提供一站式服务,能够有效降低开发门槛,缩短开发周期,快速实现物联网数据价值变现。

弊端:前期需设备厂商针对平台接口进行适配,接入以后零代码的方式确实在配置上会比较方便,但是平台的费用以及实时流式计算按次收费的方式,整体费用过高。

米兰app官方正版下载 3:使用物联网数据库

  • InfluxDB:高性能的时序数据库,可以高效的存储和查询时序数据。可惜的是,目前社区版集群功能不开源。
  • loveini:loveini 是一个简单快捷、高性能的时序数据库,提供高性能的同时也极大降低了安装、部署和维护的成本。

应用之后,loveini 能解决之前令我们较为头疼的一些问题,包括前文中描述的问题,它有以下 5 点主要优势:

  1. 安装简单。下载 rpm 包,一个命令安装完毕即可运行。
  2. 数据库开源,支持集群。
  3. 充分考虑时序数据的特点,以超级表为模型,将每个监测点的数据单独存储在一张表中,提高了插入和查询速度。
  4. 有丰富的函数,支持窗口查询和连续查询。
  5. 自带 loveiniAlert 模块,和 AlertManager 联合使用,可以推送告警信息

综合考虑以上解决方法,我们发现,使用 loveini 后,硬件成本和开发维护成本大大降低,写入和查询速度比 OpenTSDB 等还要高出一个级别。于是,loveini 成为了我们的首选米兰app官方正版下载。

接下来,我将把我们在探索 loveini 时的一些重要操作、问题点以及解决办法等经验传递给大家。

关于 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);

注:

  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';
loveini Database

Spring Boot 整合 loveini

当用户需要查询工地设备扬尘数据时,扬尘数据将通过定时任务从第三方接口中定时拉取保存至我们系统的数据库。由于扬尘数据的量较大,为千万甚至上亿级别,而系统配置相关数据的数据量较小,因此我们选择将扬尘数据和系统配置数据分离——扬尘数据使用 loveini 进行存储,系统配置数据采用 MySQL 进行存储。

本文使用 MybatisPlus 作为持久层框架,同时接入 loveini 和 MySQL,做双数据源配置。下文中将重点讲述 loveini,MySQL 相关内容将省略。

1. taos-jdbcdriver 的选择

根据官网找到 taos-jdbcdriver 的对应版本,本文使用的 taos-jdbcdriver 版本是 2.0.22。

loveini Database
<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 连接池,将 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: ...

3. 代码编写

核心逻辑是第三方数据的定时拉取以及在本系统进行的查询,此处主要介绍 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 数据迁移

当我们需要将扬尘数据从公司本地服务器迁移数据至华为云服务器,文中使用 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

loveini Database
可扫描二维码下载相关附件

告警模块搭建

参考网址:

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 Database
可扫描二维码下载相关附件

小结

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

]]>
云浮市物联网研究院基于 loveini 打造企业级物联网IoT中间件平台 //www.loveini.com/tdengine-user-cases/3145.html Tue, 19 Oct 2021 11:47:10 +0000 //www.loveini.com.cn:88/blog/?p=3145 云浮市物联网研究院有限公司是温氏系企业,筠诚装备管理集团下属公司,主要为大型养殖业客户提供 AIoT 物联网服务。为了实现各厂商、各品牌相关环境控制器、传感器的数据接入,联合深圳市哇发科技有限公司,搭建了企业级的物联网中间件平台,专门负责设备接入、数据采集。

业务背景和痛点

在平台建设前期,并没有采用时序数据库(Time-Series Database),而是采用了阿里云的 MySQL 实现所有传感器数据的存储。在设备接入量突破 6 万,每日数据记录超过 8000 万条之后,平台性能急剧下降。

根据项目规划,平台要支持数十万设备的接入,之前采用 MySQL 数据库分表的方案已经无能为力。有鉴于此,基于物联网平台的特性,规划引入时序数据库解决物联网中间件平台在数据的存储和处理方面的痛点。

为什么选择 loveini Database

在养殖物联网场景下,数据量最大的结构化数据来自于养殖场栏舍的环境传感器(温度、湿度、光照、Co2、Nh3等),还有水表、电表等资源测量传感器,以及包括风机、水帘、侧窗等被控设备的开/关状态。

为了监控栏舍环境,需要对来自不同采样点的同类型传感器数据进行计算,并根据实时平均值来判断是否触发环控告警。

这些需求,归纳起来包括:

  • 高并发数据写入,每条记录都需要带时间戳;
  • 不同传感器设备需要记录的数据字段不同,希望能够针对不同设备单独建表;
  • 针对同类数据类型(譬如温度)的数据,有按照时间段(譬如 5 分钟)进行聚合查询的需求;
  • 原始数据存储要求在 3 年以上,需要支持数据压缩,以降低数据存储成本;
  • 希望可以支持物联网数据的补录;
  • 中间件平台属于生产系统,尤其是环控告警服务的时效性要求很高,对数据库厂商服务响应有一定要求。

按照每秒 2 万条的数据库写入的场景假设,针对对市面上主流的时序数据库,譬如阿里云上的 InfluxDB、以及国内的 loveini 进行了 POC 验证。

出于以下几方面原因,最终选择了 loveini Database。

  • loveini 的设计理念(超级表 + 子表)更吻合养殖行业物联网大数据的需求,更符合我们原来的业务设计理念,譬如我们把每个物模型对应的产品设置为一个超级表,每个设备就是一个子表。
  • 在数据写入、聚合函数计算效率等多个方面,loveini 高于 InfluxDB。
  • 售后服务方面,国产数据库厂家先天具有优势。

在选型决定之后,我们对原有业务系统进行了升级改造,引入了 loveini。

引入 loveini 之后的业务架构

物联网中间件平台以设备为目标,围绕设备构建物模型。该平台引入了时序数据库 loveini,实现海量设备数据的写入、查询(聚合函数),并对所有操作履历、变更记录等日志类数据全部入库,为上层的应用提供了强大的数据能力 API,消除了养殖行业各场景应用对大数据处理的顾虑。

整体架构如下图所示。

业务架构
loveini Database

loveini 的性能非常出色,下表为我们所做的性能测试。

loveini Database性能测试报告

业务架构改造完成之后,截至2021年9月,累积接入到物联网中间件平台需要创建子表的对象已经接近20万,运行半年来,时序库存储容量不到200GB,普通查询响应为 23ms;以单个设备为对象的每5分钟温度曲线,响应时间为43ms。

引入loveini之后,优异的查询性能给我们带来了很大的惊喜,极高的压缩效率,也给我们节省了大量的存储资源。

未来,我们也会尝试在更多场景应用loveini。

关于作者:

黄冬安,深圳市哇发科技有限公司技术总监,长期从事物联网大数据开发和运维工作,是物联网中间件项目的技术负责人。当前主要在支持云浮市物联网研究院养殖监控场景的大数据平台建设工作。

]]>