需求: 项目有一个保存实时抓拍图片的功能,需要统计摄像头下每个时间点(比如一分钟)保存的图片个数,并通过线型图显示到页面上.
这很类似股票的分时K线图的功能.所以我参考了一些网上的文章,采用
Redis
来实现这个功能.
先交代一下项目里数据的一个情况:
- 摄像头个数在150个左右,单个摄像头每秒抓拍图片数平均在5张左右,150个摄像头一分钟最大抓拍图片量在200左右.
- 每天抓拍的图片总数一般在60w-100w, 峰值不超过300w.
- 每张图片的大小在8K左右.
需求分析:
- 可以显示某个摄像头下每分钟的抓拍图片个数. (时间点:分钟,数值:图片个数)
- 显示最近一天的分时图. (分时图的区间:24小时,一天的时间点个数60*24=1440)
- 缓存最近一天内的保存图片信息,以最大300w条记录算. (memory< 1K*3000000 约等于3GB, 实际情况不到2G)
接下来重点说一下这里的设计:
- 由于每秒中的图片数量不大,不用太考虑读写的压力问题,所以我每接收到一张图,则存入数据库,再写入redis当中.
- 存入redis的数据首先用到了redis中的自增操作, redis中分时数据的存储格式为hash结构,key为
count+ip
,field
为yyyy-MM-dd HH:mm
的分钟时间点,value
则为图片个数.比如192.168.0.1
这个ip的摄像头每抓拍到一张图,则redis 操作命令为HINCRBY 'count:192.168.0.1' '2018-08-10 10:30' 1
. 当然,这里会做一个定时任务,每分钟都会初始化每个摄像头当前时间点抓拍图片个数为0,操作指令为HSETNX 'count:192.168.0.1' '2018-08-10 10:30' 0
,防止查询时找不到对应时刻的数据.由于hash是不支持直接传入过期时间的,所以也需要在定时任务里删除掉24小时之前的数据:HDEL 'count:192.168.0.1' '2018-08-09 10:30'
. - 除了自增1操作外,还用到了
zset
结构,保存图片信息数据. 这里zset
的key
为info:+ip
,value
为图片信息的json
数据,如图片的地址,特征id,id等,score
则保存的时当前距计算机元年的秒数.之所以这样设计是为了方便重新统计和排序. - 前端显示数据,采用echart库的Line,通过大量数据渲染线型图.主要数据在两个数组,x轴的时间点,y轴的图片个数.两个数组,时间点和个数一一对应.这也是第2步中要做定时任务初始化的原因.
- 初次获取摄像头的时分图统计的时候,首先会读取
hash
结构中对应key
的数据,里面存储了最近24小时的统计数据,通过new一个TreeMap可以对时间进行排序,然后mao的key和value就是x,y轴所需的两个数组.获取完成后,每分钟去轮询一次查询当前摄像头,上一分钟的数据,这样能保证数据和时间点一致. - 如果需要获取最近抓拍的图片地址信息等,则可以通过
zset
结构里的ZRANGEBYSCORE
命令查询所需时间段的图片信息.也可以重新统计每个时间点的图片个数.同时这里也要在第2步的定时任务里做一个ZREMRANGEBYSCORE
操作移除24小时前的数据.
到这里整个设计思路就展示差不多就基本完成了.当然这不是全部,还有些细节,比如定时任务是否正常执行,数据持久化,服务down掉了怎么处理等.
有时间把一些设计思路的代码写出来.