1 背景
某市公安局对于车辆卡口数据统计分析有如下要求:
- 过车统计功能:根据统计时间设置,可统计指定时间段和时间类型内指定分组的过车总量,过车量趋势(根据时间类型确定基本统计粒度);对于指定分组,可下钻到每个设备的过车总量与过车量趋势分析。
- 车辆卡口设备故障类型判断:根据需求分为4类故障:设备脱机;车道流量异常;URL链接无效;校时偏差。车辆卡口设备设置了两种状态:在线/脱机状态,故障/非故障状态。
- 故障统计功能:分为实时故障(为未恢复的故障)统计与历史故障统计两类:
实时故障统计:根据指定分组统计各分组类的实时故障数量,并能展示、查询该分组内的实时故障明细;根据指定分组统计各类型的实时故障数量,并能展示、查询该分组内的实时故障明细。
历史故障统计:根据指定分组可进行卡口设备的选择,根据选择的设备以及故障类型、时间段可进行设备历史故障的查询。 - 设备统计功能:根据指定分组,可统计各分组的设备总数、在线数、脱机数、故障数、在线率。对于各分组可查看设备的故障明细。
- 车辆卡口巡检和筛选功能:根据图片抽检策略创建图片巡检任务,可对巡检结果进行统计。
2 设计思想
视图库作为车辆卡口运维模块的上游数据服务。是车辆卡口运维模块的数据来源。车辆卡口运维模块中的数据统计需求非常多,需要构建一个数据仓库(Data warehouse),对来自视图库的面向车辆主题的原始数据进行ETL操作,放入存储容器中。针对视图库中发送的数据,在数据仓库中可创建星形结构模型,在统计时可根据时间维度和行政区划维度等多维度进行OLAP分析。
视图库目前可向外提供时间粒度为1分钟的统计数据,通过消息中间件(如kafka)发送。统计数据可按设备、平台、数据类型等维度提供。在车辆卡口运维模块中需要根据视图库提供的原始粒度数据进行汇聚统计(如车辆卡口运维中判断实时故障),因而需要缓存这些1分钟粒度的基本统计数据。在实现中我们使用了时序数据库工具prometheus来持久化缓存这些1分钟粒度的原始统计数据,使用ES作为数据仓库存储容器来存储汇聚统计后的数据(如1小时的统计数据,再由1小时的统计数据汇聚统计为1天的数据)。
3 系统架构
车辆卡口运维模块的逻辑结构视图如下,其中箭头方向表示数据流向:
车辆卡口运维系统架构
视图库使用消息中间件(kafka)向车辆卡口运维模块发送的数据为:以1分钟为统计粒度的视图库收到的各数据类型的统计数据(分为设备与平台两个数据来源维度),以1分钟为统计粒度的视图库发往各订阅者的统计数据(分为设备、平台两个数据来源维度与订阅者一个数据推送维度)。这类数据被解析为prometheus指标数据发送到时序数据库prometheus中。
车辆卡口运维模块需要从统一设备服务中获取系统所管理的采集设备信息(人/车采集设备)。并将获取的设备集合作为基准设备集合进行设备故障的判断:如判断车辆卡口设备是否脱机,需针对基准设备集合中的每个设备查询其在prometheus中存放的过去30分钟过车数据是否为0。同样,对于设备与故障的统计也需基于此基准设备集合进行。
对于视图库的收发数据统计的最小粒度为1小时,统计维度可以为日,周,月,年。因而在ETL模块中使用定时任务对prometheus中1分钟的基础粒度数据进行汇总,在数据仓库中首先汇聚为1小时的数据(整点),再根据1小时的数据汇聚为一天的数据。即在数据库中存在各类型数据的小时表与天表,视图库的收发数据统计根据小时表与天表进行统计。
4 项目实施后的思考
通过两个月的开发测试,目前此项目目前已经上线,回顾此项目的开发,可以发现:在开发中我们使用了两个数据容器:
- prometheus:作为时序数据库使用,实现了在ETL中的细粒度汇聚,为实时故障的检测提供了数据依赖。
- ES:作为数据仓库的存储容器使用,其中存储的最小粒度数据为1小时统计数据。
其实在ETL设计中,我还考虑了其它几种方案和选型: - 使用kafka streams的分组汇
进行细粒度数据的汇聚,与现有方案相比,优点在于免去了引入prometheus的系统开销,但同时增加了kafka的topic,由于kafka streams只提供流式数据,对于车辆卡口故障统计无法很好实施。 - 使用内存数据库,细粒度数据存于数据库中,定时进行汇总和统计并写入ES,使用思路同prometheus,但内存数据库不持久化,出现重启的情况之前的数据会丢失。
最后综合考虑还是使用了prometheus,既实现了细粒度数据的持久化,还利用prometheus的强大时序统计功能实现了定时汇聚功能和定时数据检测功能。但由于引入prometheus也带来了系统开销的增加。
网友评论