论坛
潜水/灌水快乐,沉淀知识,认识更多同行。
ToB圈子
加入IT圈,遇到更多同好之人。
朋友圈
看朋友圈动态,了解ToB世界。
ToB门户
了解全球最新的ToB事件
博客
Blog
排行榜
Ranklist
文库
业界最专业的IT文库,上传资料也可以赚钱
下载
分享
Share
导读
Guide
相册
Album
记录
Doing
搜索
本版
文章
帖子
ToB圈子
用户
免费入驻
产品入驻
解决方案入驻
公司入驻
案例入驻
登录
·
注册
只需一步,快速开始
账号登录
立即注册
找回密码
用户名
Email
自动登录
找回密码
密码
登录
立即注册
首页
找靠谱产品
找解决方案
找靠谱公司
找案例
找对的人
专家智库
悬赏任务
圈子
SAAS
IT评测·应用市场-qidao123.com
»
论坛
›
数据库
›
Oracle
›
高频时序数据的储存与统计方案
高频时序数据的储存与统计方案
立山
论坛元老
|
2022-12-26 10:17:43
|
显示全部楼层
|
阅读模式
楼主
主题
1029
|
帖子
1029
|
积分
3087
问题背景
发电设备中常常会放置传感器(DCS)来采集数据以监控设备运转的状况,某集团设计的电力监控统计系统,需要实时采集传感器的数据后保存,然后提供按时段的实时查询统计功能。
系统设计规模将支持20万个传感器(以下称为测点),采集频率为每秒一个数据,即每秒总共会有20万条数据,总时间跨度在1年以上。在这个基础上实现任意指定时段的多个测点数据统计,包括最大、最小、平均、方差、中位数等。
系统原结构图为:
系统中,用户期望的统计响应延迟为:从20万个测点中任取100个测点,统计频率最高可能每隔若干秒调用一次,从总时间跨度中统计任意一天的数据,预期执行时间在1分钟内,另外还会有少许离线任务,最长的时间段跨度长达一年。
现有的数据中台中没有计算能力,仅存储数据,计算时需要通过RESTful接口取出数据再统计。经测试,通过RESTful接口从数据中台取数,取出100个测点一天的数据量就需要10分钟时间,还没有开始计算,取数的时间已经远远超出了完成计算的预期时间。
基于现有结构,完成上述统计任务,性能上无法达到预期要求,需要将数据重新存储。
解决办法
第一步,梳理数据和计算要求
数据结构如下:
字段名类型中文名TagFullName字符串测点名Time长整型时间戳Type数值数据类型Qualitie数值质量码Value浮点数数值计算要求为:在每秒生成20万条记录的时序数据中,任意时间段内,从20万个测点中任取100个测点的数据,分别基于每个测点的数值序列统计最大、最小、方差、中位数等结果。
第二步,确定存储和计算方案
20万测点一天的数据,仅Value字段,就要200000*86400*4字节,至少64g内存,当总时间跨度为1年时,数据量会有数十T,单台服务器内存显然装不下。多台服务器集群,又会带来很高的管理和采购成本。
简单按时间为序存储的数据,可以迅速找到相应时间区间,但即使是这样,单个测点一天也有86400条记录,20万个测点共17.28亿条,每次统计都要遍历这个规模的数据,也很难满足性能要求。
那么测点号上建立索引是否可行?
索引只能快速定位数据,但这些数据如果在外存中不是连续存储的,硬盘有最小读取单位,会导致大量无用数据量读出,使得计算变得很慢,同样也无法满足性能要求。此外,索引占用空间会随着数据量增大而增大,并且插入数据的维护开销也更大。
如果数据可以按测点号物理有序存储,并在测点号上建立索引,相比时序物理有序存储,查找时,待查找的测点记录变得紧凑了,需要读入的块也就少了。100个测点的数据存成文本约300m不到,这样即使使用外存也可以满足性能要求。
只有历史冷数据时,处理起来比较简单,定时将数据按指定字段排序即可。但实际上,每秒都会有20万个测点的新数据,因为历史数据规模巨大,如果每次获取几秒热数据都与历史数据整体按测点号、时间排序,即使不算排序,仅是重写一遍的时间成本上都无法接受。
这时,需要将冷热数据区分对待。不再变化的冷数据可以按测点次序准备好。这里有一点变通,因为要将非常早期的数据删除(比如一年前的),如果所有冷数据都按测点排序时,会导致数据维护比较麻烦,删除早期数据会导致重写一遍所有数据。因此,可以设计为先按时间分段,每段时间内的数据按测点、时间有序,整体数据还是按时间有序。任务需求是按天计算,这里按天分段就比较合适,更长跨度的离线计算性能损失也不是很大。每当一天过去时,将昨天数据按上述规则排序后存储,当天的数据作为热数据处理。但是,当天内的数据量还是太大了,依然无法全部装入内存,还需要再分。
经过一些测试后确认,我们发现将数据按热度分为三层可以满足要求。第一层,十分钟内的热数据通过接口读入内存;第二层,每过10分钟,将过去10分钟的内存数据按测点、时间有序保存到外存;第三层,每过一天,将过去24小时内的所有每10分钟的数据按测点、时间有序归并。总数据为:一年的数据由365段每天数据,加144段当天数据和一段内存数据。
分层后的冷热数据属于不同的数据源,需要独立计算同源数据的结果后,再将结果合并起来,算出最终的统计结果。即使计算方差、中位数这种需要全内存统计的情况,100个测点一天的数据量,也只需要64m内存。
第三步,确定技术选型和方案
从上述的存储方案中得知,需要将实时数据按时间分段,段内按测点号、时间物理有序存储,常规数据库显然没办法做到这点。此外,拆分数据需要可以支持按自定义时间段灵活地拆分;数据存储时要具备高性能索引;冷热数据属于不同层(不在同一个数据源),计算时需要分别计算后再合并。
完成该任务,用Java硬编码工作量巨大,Spark写起来也很麻烦。开源的集算器SPL语言提供上述所有的算法支持,包括高性能文件、物理有序存储、文件索引等机制,能够让我们用较少的代码量快速实现这种个性化的计算。
取数不能再用原系统的RESTful接口,也不合适直接通过API从DCS获取数据。用户方商定后引入kafka缓冲数据,屏蔽DCS层,同时还可以将DCS的数据提供给不同的消费者使用。变更后的系统结构图如下:
说明:
DCS系统每秒推送20万个测点数据至Kafka MQ。
Kafka MQ到SPL:使用SPL基于Kafka API封装的Kafka函数,连接Kafka、消费数据。
内存缓冲:循环从Kafka消费数据(kafka_poll),每轮循环确保10秒以上的数据量,将每轮前10秒的数据补全后,按测点、时间序,保存成文件并读入内存。
分层数据文件:按不同时间段将冷热数据文件分层。
统计时将冷热数据混合计算。
支持每个测点名对应一个CSV文件作为数据源计算。
统计接口以HTTP服务方式供外部应用调用并将统计结果通过回调接口返回给外部应用。
第四步,实施优化方案
现有的RESTful接口取数太慢了,接口变为从kafka消费数据。存储数据时,将字符串类型的测点名数字化后保存,以获得更小的存储量和更好的运算性能。
在第二步中已经提到,数据量较大时,无法将数据都放在内存中计算,所以考虑采用冷热分层方案,将数据分为三层,每天的冷数据按测点号、时间有序(下文中的所有外存文件存储均采用该序,不再重复说明),用组表存储,因为大表对性能的影响很大,存储成组表有利于提升系统整体性能;当天的每10分钟的冷数据用,集文件存,因为集文件创建和使用都更简单,用来存储小表会很便捷,也不会因为索引块而降低存储效率;10分钟内的热数据从kafka直接读到内存,因为数据本身是通过kafka接口获取的,另外数据可能有一定的延迟,不适合每秒取数即写出。
测试后发现,10分钟内的热数据,从kafka获取后再解析json,不但需要消耗大量内存,而且解析json也需要花费很长的时间。这样在内存中直接加载热数据是没办法用来统计计算的,所以将热数据改为每10秒存成一个集文件。
接下来开始实现统计计算部分。每天组表中的冷数据计算较快,但是当天的144个集文件计算很慢。通过计算可以知道,每10分钟的数据量约1.2亿条记录,这个规模的数据可以用组表来存储,另外还可以再加一层每2小时一个组表文件,来减少当天总文件数的数量(从144个变成了24个)。实际上,计算时采用的二分查找是对单个文件内有序的测点号使用的,减少了文件个数,也就是减少了总查找次数。
最终,我们把数据分成了4层。第一层:延迟10秒的集文件热数据;第二层,每10分钟的组表冷数据;第三层,每2小时的组表冷数据;第四层,每天的组表冷数据。由于每层数据都按测点号、时间有序,所以每一层都可以用归并,快速生成下一层数据文件。
这时的冷数据计算已经很快了,可以满足实际使用,但是热数据的计算相比冷数据还是很慢。观察发现,热数据的所有集文件都加起来大约3G,不算很大,内存可以装下。实际测试,把文件读到内存中再查找相比直接外存文件查找可以快出好几倍。
已知的统计计算,分为最大值、最小值、中位数、方差、平均值等,不尽相同,但是之前的数据查找是一样的。都用二分法,找出对应测点号组的数据,再用时间过滤,即可得到相应的value值。
实测效果
经过几天时间的SPL编码、测试,优化的效果非常明显。优化之后的测试结果如下(耗时为毫秒):
测点数
时间段105010010分钟4675868541小时1739388545456小时25997489131381天49231626430254说明:测试环境使用的机械硬盘,对并发计算不友好,更换为固态硬盘后,测试结果还会有较大的提升。
后记
解决性能优化难题,最重要的是设计出高性能的计算方案,有效降低计算复杂度,最终把速度提上去。因此,一方面要充分理解计算和数据的特征,另一方面也要熟知常见的高性能算法和存储方案,才能因地制宜地设计出合理的优化方案。本次工作中用到的基本高性能算法和存储方案,都可以从下面这门课程中找到:
点击这里学习性能优化课程
,有兴趣的同学可以参考。
传统数据库的功能比较单一,只能解决一个环节的问题,比如内存数据库解决热数据问题,大数据平台解决冷数据。而当前问题需要多种技术组合,如果运用多种产品混合实现,又会带来架构的复杂性,增加系统的风险。而且业界中的大数据库产品的架构也较为死板,对存储层基本不提供可编程能力,很难基于这些产品实现某些特殊设计的方案。
相比之下,集算器则拥有开放的技术架构和强大的编程能力(SPL语言),可以被深度控制,从而实现各种因地制宜设计的方案。
SPL资料
SPL下载
SPL源代码
欢迎关注我的公告号:字母哥杂谈,回复003赠送作者专栏《docker修炼之道》的PDF版本,30余篇精品docker文章。字母哥博客:
zimug.com
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!
本帖子中包含更多资源
您需要
登录
才可以下载或查看,没有账号?
立即注册
x
回复
使用道具
举报
0 个回复
倒序浏览
返回列表
快速回复
高级模式
B
Color
Image
Link
Quote
Code
Smilies
您需要登录后才可以回帖
登录
or
立即注册
本版积分规则
发表回复
回帖并转播
回帖后跳转到最后一页
发新帖
回复
立山
论坛元老
这个人很懒什么都没写!
楼主热帖
IoTOS-v1.5.3 新增 智能诊断&会话记录 ...
【学习笔记】WPF-01:前言
基于SqlSugar的开发框架循序渐进介绍( ...
网络安全-技术与实践 书本习题练习 ...
CentOS7 单机版使用kubeadm安装K8S ...
IO流的使用
开源直播课丨大数据集成框架ChunJun类 ...
Python中可以用三种方法判断文件是否存 ...
WEB安全基础入门—身份验证漏洞 ...
解读数仓常用模糊查询的优化方法 ...
标签云
AI
运维
CIO
存储
服务器
浏览过的版块
网络安全
Mysql
Nosql
.Net
SQL-Server
分布式数据库
云原生
Java
鸿蒙
快速回复
返回顶部
返回列表