文章大纲

统计用电量,没想到居然错了近一整年

2025-07-04 18:48:29

场景描述

因为误更了文件,导致系统定时计划停了三四天。

所以这一周都在加班加点的写数据恢复的程序(早期写了部分,也需要重新调整)。

简单说:就是这三四天本该服务器自动干的活儿,然后漏掉了,我现在得集中把这些活儿都给补上。

典型的自己给自己挖坑。


问题发现

写用电量统计数据恢复程序时,意外发现自己之前写的统计程序不严谨。

看了下时间,正好过了快将近一年。


问题就在于上面这几行代码:

$lastHourEnergyData = $serviceStatisticEnergy->getHourFirstData($equipmentId, $lastHourTime);
$lastHourEnergy = isset($lastHourEnergyData['value']) ? $lastHourEnergyData['value']:0;
$attributeData['attribute_value'] = $curEnergy < $lastHourEnergy ? 0:$curEnergy - $lastHourEnergy;
if(0 == $attributeData['attribute_value']){
//如果电表度数没有增长,就上报异常
throw new \Exception("electricity statistic abnormal:".$deviceId);
}
$serviceStatisticEnergy->storeAttributeDiffValue($equipItem, $attributeData, 'hour', $lastHourTime);

上面代码逻辑就是:上一个小时用电量 = 当前电表读数 - 上一个小时一开始的电表度数


定时计划任务如果是从0分开始,上面代码实现的结果倒也没什么问题。

但现在定时计划任务是从每小时的第10分钟执行的,如下:

bash
10 * * * *  /usr/bin/curl http://xxx.com/admin/cronjob/electricityHourlyConsumed


这样带来的问题就是:

上面公式里当前电表的读数,实际上包含了当前这一小时开头10分钟的用电量,按照公式推算,上一个小时的用电量就多统计了10分钟。

正确的代码逻辑应该是:

上一个小时用电量 = 当前这个小时一开始的电表度数 - 上一个小时一开始的电表度数


问题概括

之前整个程序的逻辑是:

  1. 上一个小时用电量 = 当前电表读数 - 上一个小时一开始的电表度数
  2. 当天用电量 = 当前电表读数 - 当天一开始的电表度数
  3. 当月用电量 = 当前电表读数 - 当月一开始的电表度数


上面统计逻辑的不严谨之处解释如下:

  1. 每小时用电量多算了10分钟
  2. 每天的用电量少算了50分钟
  3. 每月的用电量也少算了50分钟


最终修复

为了修复上面统计逻辑的不严谨,除了修改上一个小时用电量的计算公式之外,还加入了2处逻辑,代码如下:

txt
//同步更新当天的用电量数据
...

//凌晨1点的时候,同步更新前一天的用电量数据,否则每天用电量统计少算了50分钟(定时计划从第10分钟开始的)
if(1 == $curHour){
    ...
}

//同步更新当月的用电量数据
...

//1号凌晨1点的时候,同步更新上个月的用电量数据,否则每月用电量统计少算了50分钟
if(1 == $curHour && 1 == $curDay){
    ...
}


本文为翟码农个人博客技术主题下php分类里的原创文章,转载还请注明出处:http://www.zhai14.com/blog/never-thought-that-the-statistic-of-electricity-consumption-has-been-false-for-nearly-a-whole-year.html


我的心得

看到文章这里,我们可以看出,开发用电量统计业务,主要实现好下面2个工作就好了

  1. 把每小时/每天/每月的第一笔电表度数存储下来
  2. 读取第一步骤保存的数据,进行求差运算,再保存每小时/每天/每月的用电数据


前一天的用电量,本来是可以把前一天统计好的每小时用电量累加起来;同理,上个月的用电量,也是可以把上个月统计好的每天用电量累加起来。

但经过此次代码的不严谨,我们发现,如果用的是累加方式,数据偏差就更厉害。从这个角度来看,都通过电表读数求差的方式来计算用电量,反而更容易让人放心。



我要评论
评论列表