上篇讲了调度与补数,解决的是"数据怎么不断"。
本篇解决更隐蔽的一半:数据怎么不错。
一、容错让数据不要污染分析结果
上篇解决了"数据别断"。但断线是看得见的故障——监控处理会报警、看板会出现空洞。真正难处理的是另一类:
系统在正常采集,数据也在正常入库,但进库的值是错的。
这类故障没有任何告警会触发,往往要到月度报表对不上账时才被发现,而那时原始数据可能已经被覆盖丢失了。
1. 质量位:0 和"没采到"必须区分开
这是我认为低频采集里最该做、却最常被忽略的一件事。
采集失败时,很多系统的做法是"写个 0 补进去"或者"跳过不写"。但两个做法都是错的:
- 写 0:下游算平均值时,0 会被当成真实值参与计算。温度平均下来被拉低,能耗统计直接失真,而且没人会发现
- 不写:下游分不清"这个时刻没数据"和"这个时刻是 0",同样会算错
正确做法是给每条数据带质量位(Quality)。这个模式在工业领域有现成标准可参考——OPC DA 的 Good / Bad / Uncertain 质量体系,以及 OPC UA 的 StatusCode。建议至少区分:
| 质量 | 含义 |
|---|---|
Good | 正常采集 |
Uncertain | 采集成功但值可疑(如死值、超量程但可能是真实尖峰) |
BadTimeout | 通信超时 |
BadCommError | 通信错误、校验失败 |
BadOutOfRange | 超出量程 |
Stale | 值长时间未变化,怀疑传感器或通信卡死 |
有了质量位,下游就能明确:聚合时只取 Good;统计完整率时区分"缺数据"和"坏数据"。
2. 重试与熔断:不是所有错误都该重试
该重试的:超时、连接被拒、临时性网络抖动。不该重试的:校验错误(重试也会错)、地址不存在(重试一万次也没有)、协议不支持。
重试策略建议:
- 指数退避 + 随机抖动(jitter)。加抖动很重要——所有站点同时断网又同时恢复时,如果重试时间完全一致,会形成"重试风暴",把刚恢复的网络再次打垮
- 重试次数有上限,超过就标记 Bad 并告警
然后是熔断,这个尤其重要:
// 连续失败 N 次后,暂停该站点一段时间,不再参与调度 if (failStreak >= threshold) { openUntil[siteId] = now + cooldown; }熔断解决的是一个真实问题:一个坏设备会拖垮整轮采集。如果每个站点超时 30 秒,20 个坏站点就是 10 分钟——整轮采集周期被拉长,好站点的数据也跟着延迟。
熔断后该站点暂时不采集,坏站点的影响被隔离。但要注意:熔断期间该站点完全没有数据,必须在监控里明确暴露,不能"熔断了就没人管了"。