美文网首页
统计功能设计

统计功能设计

作者: 柠檬小猪 | 来源:发表于2023-05-08 17:21 被阅读0次

    数据量太大的情况下,现场计算一定会超时;

    统计功能步骤

    1.查询并计算数据(简单)

    2.将数据存到中间表(简单)

    3.修改统计数据的时候更新中间表(复杂)

    4.实时刷新展示数据(复杂又麻烦)

    中间表使用

    以告警业务的统计举例,设计一套快速稳定的功能

    查询时(查询包含了初始化,增量新增,更新)

    1.查询:当天的直接计算(当天数据变化快),之前的数据从中间表获取;

    2.初始化:中间表取出数据后,按日期检测是否有数据为空,如果缺失(比如统计3,4,5月的数据,其中4月数据为null,说明4月数据没生成过),去业务表中获取并计算;然后保存到中间表;第一次使用就是初始化的效果。

    3.增量新增:一般情况下只有昨天的数据需要新增。

    4.更新:如果老数据有更新的可能,需要再次去业务表里查询并计算;(比如未处理状态的告警,需要去查询是否已经处理完了)

    这里有两个处理方式。

    4.1.业务表修改时加上需要修改标识,或直接修改中间表,

    4.2.定期或查询时去复查可能更新的数据,最好定个范围;比如一个月内的未处理告警,每次点击统计查询的时候会去业务表复查。

    我是两个方式都加上了,团队开发的时候4.1可能无法做到全部修改都覆盖到,而且测试环境经常会有数据库直接修改数据。

    统计颗粒度权衡

    这么麻烦的设计,如果只对应一个功能就浪费了;

    怎么样让统计表可以通用的同时还能保证效率?

    首先是统计的颗粒度,按告警类型,告警状态,告警地区,告警日期分别统计;

    假如要展示温度告警的统计,那把高温告警和低温告警相加后展示;但是如果太细了,计算就会很频繁,那就失去了统计表的效率,如果太粗了,复用性就很差;比如只按市区统计,客户想看区县的统计数据就看不到了。

    可以用空间换时间,例如同时保存县区和市区的统计数据,同时保存月和日的统计数据;

    保证每次计算量不要太大,比如查询3月1日到5月4日的统计数据,只需要计算3月+4月+5月1号+5月2号+5月3号+5月4号+5月5号,统计一年内的也不会超过80次的循环相加。

    数据同步注意事项

    统计难度最大的就是数据同步,如果处理不好,很容易就会出现数据对不上的问题。

    继续用告警功能举例,首先要确定告警数据在哪些功能里会被修改,如果项目代码写的规范,只需要在告警的修改方法统一处理即可。

    具体步骤是

    1.这条告警状态被修改了,为处理->以处理;插入两条redis数据key1=修改前状态+告警类型+告警地区+告警日期;key2=修改后状态+告警类型+告警地区+告警日期;值随意,主要是key。

    2.统计表查询时如果查询到redis中key对应的数据,就要重新计算,然后替换统计表里的数据。(一定要记得替换,这里容易出bug)

    由于我计算统计数据的最小查询量是一天(把一整天的告警数据查询出来,在按照条件来分类统计,比按条件多次访问数据库更有效率),所以我的key只有日期。key1=告警日期;key2=告警月;(同时保存了月和日的统计所以要一起更新)

    如果发生了正好每天的数据都修改了,然后再查询一次,那就和初始化一样,非常慢,还可能超时。

    优化

    1.使用消息队列,告警状态被修改了,保存redis数据的同时插入一条延迟消息,5分钟后更新相关统计(为什么要延迟,如果修改一条就要重新统计一次,那太浪费资源了,延迟5分钟可以把5分钟内的所有修改一起更新了);

    2.redis保存的值不再是随意写的,从0开始累加,设定一个阈值,比如10,超过10就更新相关统计。

    这些操作都是为了防止统计更新集中在查询的时候,这两个设计很像mysql的刷盘机制,所以好的设计都是可以互相借鉴的,经典永流传;但是实际运用上查询比修改更频繁;上述优化是可选的。

    功能设计的越复杂,用起来更顺畅,但是维护起来更难;所以量力而行。

    最酷炫的实时刷新怎么做

    打开统计页面,页面上的数字会根据告警的新增修改,实时变化。

    这个要借助websocket,和定时任务来实现。

    未完待续...

    相关文章

      网友评论

          本文标题:统计功能设计

          本文链接:https://www.haomeiwen.com/subject/ezoejdtx.html