物联网这个词被喊了很多年,但真正让做数据的人头疼的,从来不是"设备能不能联网",而是设备连上之后,那些一刻不停、源源不断、还时不时抽风的数据该怎么接、怎么存、怎么算。我前后参与过几个设备接入量在几千到几万台量级的项目,从最开始的"能存下来就行",到后来被查询慢、存储贵、告警乱这三座大山反复教育,逐渐摸索出一套相对稳定的做法。这篇内容聊的就是物联网中的大数据应用:一条从传感器上报的原始点位,到最终变成看板上一条趋势线、一条告警、一份能耗报表的完整链路,中间涉及的核心技术选型、参数计算、踩过的坑以及可以直接抄作业的配置。适合正在做设备数据平台的后端、数据开发、以及需要判断方案可行性的技术负责人看;如果你是刚接触这个方向的新手,里面关于协议、时序库、流处理的基础解释也尽量写成了人话,跟着读不会卡壳。
1. 先搞清楚"料"长什么样,再谈怎么"下锅"
很多人一上来就问用哪个数据库、用不用 Flink,我觉得这个顺序反了。物联网数据和业务库里的订单、用户表完全是两种生物,你得先承认它的"野",架构才有意义。
1.1 四条数据特征决定了架构底色
我把物联网数据的特征归结为四条,这四条几乎是所有技术选型的出发点。
第一条是写多读少、写入量级远超传统业务。一个中型工厂五千个测点、五秒一次上报,就是每秒一千条写入,一天八千多万条。而查询往往是少量人看报表、看趋势,读写比可能是一百比一甚至更高。这意味着任何带行锁、带 B+ 树随机写的存储引擎都会被拖垮,选型时必须优先考虑顺序追加写。
第二条是强时间属性。每条数据天然带时间戳,查询几乎永远带时间范围条件——"最近一小时"、"昨天全天"、"这个月和上个月对比"。时间就是天然的主键和分区键,这一点决定了时序数据库(Time Series Database)比通用关系库更合适。
第三条是数据价值随时间衰减极快。秒级原始点位在故障回溯时价值极高,超过一周基本没人看,但按小时聚合的均值、最大值、累计量却要留好几年,用来做能耗分析、设备寿命评估。所以存储必须分层,不能一个策略存到底。
第四条是数据质量天然不可靠。网络抖动导致乱序、设备重启导致时间戳跳变、传感器老化导致数值漂移、信号盲区导致整段缺失。这些问题不是偶发,是常态。如果你的链路设计里没有考虑乱序和去重,上线第一周就会看到莫名其妙的尖刺和负数。
这四条摆在一起,其实已经能推出结论了:需要一个高吞吐顺序写的时序存储、需要一个能处理乱序的流式计算、需要冷热分层、需要一套数据质量校验。至于具体产品,反而是后面的事。
1.2 为什么传统数据栈在物联网场景里会翻车
我见过最典型的翻车方式,是把设备数据直接怼进业务用的关系型数据库。前三个月没事,因为只有几百个测点;等接入量涨到几千,DBA 开始抱怨磁盘满、慢查询日志刷屏,最后不得不每周手动删历史数据。
问题出在几个地方。关系库的行存结构对"只查某一列的时间序列"这种访问模式极不友好,一次查询要扫大量无关字段;索引维护成本随写入量线性上升,高频写入时索引页分裂会吃掉大量 IO;而且关系库没有原生的时间分区和自动降采样能力,只能靠定时任务手工搬数据,运维负担极重。
另一个常见误区是拿通用缓存当消息队列用。设备上报直接写进缓存,消费端再读出来落库。这个方案在数据量小的时候看着挺优雅,但一旦消费端挂了或者变慢,缓存里堆积的数据既没有持久化保障,也没有消费位点管理,丢数据是迟早的事。我吃过这个亏,后来老老实实换成了带持久化和分区能力的消息中间件。
提示:判断一个存储是否适合物联网场景,问三个问题就够了——写入是不是顺序追加?有没有原生时间分区和 TTL?能不能在库内做降采样聚合?三个答案都是"是",基本可以进候选名单。
2. 整体架构怎么搭:从设备端到应用端的四层拆解
架构这东西不必画得很花哨,我习惯按"采集、接入、存储、计算应用"四层来拆,每一层边界清楚,替换起来也方便。下面逐层说选型的逻辑,重点讲为什么这么选,而不是选了什么。
2.1 采集层:协议选型和上报策略比协议本身更重要
采集层常见的协议大致分三类。一类是工业现场总线类的,像 Modbus、PLC 私有协议,特点是稳定但封闭,通常需要在边缘侧加一台网关做协议转换。一类是轻量级物联网消息协议,像 MQTT、CoAP,适合带宽受限、设备算力弱的场景。还有一类是设备厂商自定义的 HTTP 上报,好处是接入简单,坏处是开销大、不适合高频。
选型的核心不是哪个协议更先进,而是你的设备侧有没有改造空间。如果设备是十年前的老机床,你只能在边缘网关上做转换,别指望它直接说 MQTT;如果是自己研发的新硬件,那优先选长连接、低开销的协议,能省下可观的流量和电量。
比协议更容易被忽视的是上报策略。我见过太多项目默认"越频繁越好",结果数据量翻十倍,价值没增加多少。实践中我一般按数据变化特性分组:温度、压力这类缓变量,变化超过阈值才上报(变化上报),配合五分钟一次的兜底心跳;电流、振动这类快变量,按固定频率上报;开关量用状态变更加边沿触发。这样一刀切下去,整体数据量往往能砍掉一半以上,而关键信息一点没丢。
还有一个细节:时间戳由谁打。如果完全信任设备时间,设备没电重启后时间归零,数据就会跑到 1970 年去。我的做法是双时间戳——设备侧打采集时间,网关或接入层打接收时间,入库以设备时间为准但用接收时间做兜底校验,两者偏差超过阈值就标记为可疑数据,走单独的隔离表。
2.2 接入层:消息中间件的取舍与分区设计
接入层的职责很明确:扛住并发连接、做协议解析和格式统一、把数据可靠地投递到下游。这里几乎绕不开消息中间件。
选型上我主要看三个指标:吞吐、持久化保证、以及分区模型是否适合按设备维度扩展。实际项目里用得比较多的是 Kafka 这一类分区日志模型的产品,原因是它能顺序写盘、支持多消费者组独立消费(同一份数据既能给实时告警用,也能给离线入库用),而且分区可以按设备 ID 做哈希,保证同一台设备的数据落到同一分区,天然有序。
分区数怎么定,是个实打实要算的问题。假设峰值写入每秒五万条,单分区实测能稳定处理三千到五千条,那至少要十个分区,再留一倍余量就是二十个。但分区也不是越多越好,分区多了文件句柄、副本同步、再均衡开销都会上去,一般控制在消费者线程数的整数倍比较舒服。
Topic 的设计同样有讲究。我习惯按"业务域 + 数据类型"拆,而不是所有设备一个 Topic。比如设备遥测、设备事件、设备告警分开,原因是这三类数据的量级、保留时长、下游消费者完全不同,混在一起会导致慢消费者拖累快消费者,也没法针对性地设保留策略。
主题命名示例(按业务域分层,避免单主题承载所有类型) iot.telemetry.raw 遥测原始数据,保留 7 天 iot.event.state 状态变更事件,保留 30 天 iot.alarm.trigger 告警触发记录,保留 180 天注意:不要用设备 ID 直接当 Topic 名。几万台设备就是几万个 Topic,元数据管理和连接开销会先把你压垮。设备维度用消息体的字段或分区键表达,Topic 保持粗粒度。
2.3 存储层:热温冷三层,各司其职
存储是成本大头,也是最容易设计得粗糙的一环。我的思路是分三层,每层职责单一。
热层放最近七天到三十天的原始数据,用专门的时序数据库,要求写入快、按时间范围查询快、支持库内降采样。这一层的数据要能支撑故障回溯和实时看板。
温层放按分钟或小时聚合后的数据,保留一到两年,用于趋势分析和对比报表。数据量大概是原始层的几十分之一,用同一套时序库或者列式存储都能扛。
冷层放按天、按月聚合的结果和归档的原始文件,保留三年以上,主要应对合规留存和长周期分析。这一层追求的是单位存储成本最低,查询慢一点可以接受。
分层的核心收益是成本。同样一年的数据,全存原始可能要几十 TB,分层之后热层只占几个百分点,整体成本能降一个数量级。这里必须提一句:分层不是建三个库就完事,关键是降采样任务要稳,一旦聚合任务断了,温层就出现空洞,后面补数据非常痛苦。我一般会给聚合任务配独立的水位监控,超过预期时间没产出就告警。
2.4 计算层:流批一体的边界在哪里
计算层要回答一个问题:哪些指标必须实时算,哪些可以离线算。
我的划分标准是"人会不会立刻行动"。温度超限要立刻停机、电流异常要立刻检修,这类指标走流式计算,端到端延迟控制在秒级;月度能耗排名、设备利用率、OEE 这类指标,人第二天看也一样,走批处理,成本低得多、逻辑也好维护。
流计算部分,重点是状态管理和乱序处理。物联网数据乱序是必然的,网络重传、网关缓存补传都会导致后到的数据时间戳更早。如果直接用处理时间窗口,结果会不准。所以一定要用事件时间加水位线,允许一定迟到时间,超过水位线的数据走侧输出单独处理,而不是直接丢弃。
批处理部分没什么特别的,注意两点:一是幂等,同一批数据重跑结果要一致;二是分区裁剪,按日期分区,查询时务必带上分区条件,否则全表扫描能把集群拖垮。
3. 核心实操:一条从传感器到看板的完整链路
前面讲的是骨架,这一节把肉填上。我以一个虚构的"设备状态监测平台"为例,把数据模型、容量估算、流处理作业、存储表结构、看板与告警这几步完整走一遍。
3.1 数据模型:设备影子与标签体系
数据模型没设计好,后面所有查询都会别扭。我的做法是分两层建模。
第一层是设备元数据,存在关系库里,包括设备编号、型号、所属产线、安装位置、投运时间、量程、精度等级。这部分变化极少,读多写少,关系库最合适。
第二层是设备影子,也就是设备的实时状态快照,包括最新值、最新上报时间、在线状态、当前告警等级。这一层的作用是让看板和接口不用去时序库里捞最新一条,直接读影子就行,响应快得多。影子的更新可以放在流处理作业里,每来一条数据就 upsert 一次。
点位命名是另一个容易埋雷的地方。我强烈建议用层级化的标签体系,而不是把点位信息塞进指标名里。比如不要叫line1_machine3_temp,而是指标名统一叫temperature,然后用line=line1, machine=machine3这样的标签区分。原因很简单:指标名是有限的、可枚举的,标签是动态的,按标签过滤比按名字模糊匹配高效得多,而且新增设备不需要改表结构。
不过标签也不能乱加。标签值的组合数(也就是基数)如果爆炸,索引会撑不住。像设备编号这种几千上万的标签可以接受,但像"消息 ID"、"会话 ID"这种每次都不同的值绝对不能做标签,必须放在数据字段里。我见过有人把请求 ID 当标签,一天的基数增长到几百万,库直接卡死。
3.2 容量估算:把账算在前面
做方案评审的时候,我最怕听到"数据量应该不大"。容量必须算,算完你才知道该选什么规格、该不该分层。
假设场景是这样:五千个测点,其中四千个缓变量按五分钟上报,一千个快变量按五秒上报。
缓变量部分:4000 ÷ 300 秒 ≈ 13.3 条/秒。 快变量部分:1000 ÷ 5 秒 = 200 条/秒。 合计约 213 条/秒。
这个数字看着不大,但乘上时间就吓人了。每天 213 × 86400 ≈ 1840 万条。每条数据换算成存储,包含时间戳、设备标识、指标名、标签、数值、质量位,序列化后大概 150 到 250 字节,取 200 字节算,一天原始数据约 3.7 GB,一年约 1.3 TB。
时序数据库普遍有比较好的压缩比,列式存储加时间戳差分编码、数值差分编码,实测压缩比在 8 到 15 倍之间,取 10 倍,一年实际占用约 130 GB。这个量级用单机时序库完全扛得住。
但要注意,这只是原始层。如果再加上降采样后的分钟级数据(1840 万 ÷ 60 ≈ 30 万条/天,几乎可以忽略),总量还是很温和。真正会把成本拉起来的是标签基数和索引膨胀,而不是数据行数本身。
再算一下写入吞吐。213 条/秒对应约 42 KB/秒,峰值如果按均值的三倍算,也就 130 KB/秒。这个量级对时序库来说非常轻松。但如果测点扩到五万,就是 2 条千/秒左右,这时候就要考虑分片和集群了。所以容量估算的意义不只是算存储,更是提前判断什么时候需要扩容、扩哪一层。
3.3 流处理作业:乱序、去重与窗口聚合
流处理这块我写过不少作业,最容易出问题的永远是乱序和重复。下面这段是核心逻辑的示意,用的是流式 SQL 的写法,思路通用。
-- 事件时间语义,允许 30 秒乱序,超时数据走侧输出 CREATE TABLE telemetry_source ( device_id STRING, metric STRING, ts TIMESTAMP(3), value DOUBLE, quality INT, WATERMARK FOR ts AS ts - INTERVAL '30' SECOND ) WITH ( 'connector' = 'kafka', 'topic' = 'iot.telemetry.raw', 'properties.bootstrap.servers' = 'broker-1:9092', 'properties.group.id' = 'rt-aggregation', 'scan.startup.mode' = 'group-offsets', 'format' = 'json' ); -- 分钟级聚合,同时算出均值、最大最小和样本数 INSERT INTO telemetry_1min SELECT device_id, metric, TUMBLE_START(ts, INTERVAL '1' MINUTE) AS win_start, AVG(value) AS avg_value, MAX(value) AS max_value, MIN(value) AS min_value, COUNT(*) AS sample_cnt FROM telemetry_source WHERE quality = 0 -- 只统计质量位正常的数据 GROUP BY device_id, metric, TUMBLE(ts, INTERVAL '1' MINUTE);这段逻辑里有几个点值得展开说。
水位线设多久,取决于你的最大乱序程度。我一般先用一周的数据统计到达延迟分布,取 P99 再加一点余量。设 30 秒意味着一条数据最晚在事件时间 30 秒后仍会被纳入计算,代价是聚合结果会晚 30 秒输出。如果业务对实时性要求极高,可以缩短水位线,同时接受少量数据被侧输出。
去重怎么做。设备补传会导致同一时间戳的数据重复投递。我的做法是在写入前按"设备 + 指标 + 时间戳"做幂等,时序库如果支持主键去重就直接依赖存储层,不支持的话在流作业里维护一个短窗口的状态做去重。状态不能留太久,否则内存撑不住,一般保留两到三个水位线周期就够。
质量位一定要参与计算。传感器故障时上报的值往往是量程边界值或者零,如果直接做均值,报表会莫名其妙偏低。所以聚合时必须过滤质量位异常的数据,同时在结果里保留样本数,样本数过少的窗口直接标记为不可用,避免误导。
3.4 存储表结构:按时间分区的建表与降采样
时序库建表有几个硬性约束要遵守,我以常见的时间序列表结构来说明。
-- 原始表:按天分区,保留 30 天,按设备和指标建立标签索引 CREATE TABLE telemetry_raw ( ts TIMESTAMP NOT NULL, device_id VARCHAR(64) NOT NULL, metric VARCHAR(64) NOT NULL, value DOUBLE, quality SMALLINT DEFAULT 0 ); -- 分区策略:一天一个分区,过期自动清理 -- 保留策略:hot 层 30 天 ALTER TABLE telemetry_raw SET TTL = '30 days'; -- 分钟聚合表:保留 2 年,作为温层主查询入口 CREATE TABLE telemetry_1min ( win_start TIMESTAMP NOT NULL, device_id VARCHAR(64) NOT NULL, metric VARCHAR(64) NOT NULL, avg_value DOUBLE, max_value DOUBLE, min_value DOUBLE, sample_cnt INT ); ALTER TABLE telemetry_1min SET TTL = '730 days'; -- 日聚合表:保留 5 年,用于长周期报表 CREATE TABLE telemetry_1day ( day_start DATE NOT NULL, device_id VARCHAR(64) NOT NULL, metric VARCHAR(64) NOT NULL, avg_value DOUBLE, max_value DOUBLE, min_value DOUBLE, sample_cnt BIGINT ); ALTER TABLE telemetry_1day SET TTL = '1825 days';建表之后还有一个动作容易被漏掉:连续聚合。很多时序库支持把聚合定义成持续运行的物化视图,原始数据写入后自动滚动聚合到分钟表、再从分钟表滚动到日表。这比写定时任务省心,因为它是增量计算,不会每次都全量扫一遍。
如果数据库不支持连续聚合,那就老老实实用定时任务,但要注意两点。一是任务必须支持断点续跑,记录上次处理到的水位,重跑时只处理增量。二是任务要有补偿机制,如果发现分钟表某个时段缺数,能从原始表重新算一遍补进去。我吃过一次亏,聚合任务因为一次网络抖动挂了两小时,没人发现,直到一周后做月度报表才发现中间有一段是空的,补数据补到凌晨。
3.5 看板与告警:阈值不是拍脑袋定的
应用层看起来简单,其实坑不少。看板方面,我的经验是永远不要直接查原始表。一个页面上七八个图表,每个都去扫原始数据,用户一刷新就打出几十个重查询。正确做法是所有看板都建立在聚合表上,并且强制带时间范围和设备过滤条件。
告警这块更值得说。我见过太多项目把阈值写死成常量,上线后要么天天误报,要么漏报关键异常。比较靠谱的做法是三步走。
第一步是静态阈值兜底,按设备型号给一组默认上下限,这个值来自设备手册或者试运行期间的历史分位数,比如取 P1 和 P99 再加一点余量。
第二步是动态基线。设备工况是变化的,白天负载高、夜里负载低,用同一个阈值必然误报。可以用滑动窗口的历史均值加减若干倍标准差作为动态区间,窗口取七天比较合适,能平滑掉周末和工作日的差异。
第三步是去抖与抑制。告警触发后不要立刻发,而是要求条件持续满足若干秒或若干个采样点才确认,这叫去抖。同时要有抑制规则:同一台设备的同一类告警,五分钟内只发一次;上级汇总告警在下级告警未恢复时不再重复发。这两条规则能把告警量压掉七八成,值班人员才不会被淹没。
去抖与抑制规则示例 1. 连续 3 个采样点(约 15 秒)超过阈值,才正式触发 2. 同设备同指标告警,5 分钟内只投递一次 3. 设备离线告警延迟 60 秒触发,避免网络短暂抖动误判 4. 维护工单期内,该设备的告警自动静默4. 常见问题与排查实录
这一节记录的都是真实踩过的坑,很多在网上搜不到标准答案,只能靠一层层剥。
4.1 数据断点与乱序:先分清是"没采到"还是"没存到"
看板上出现一段空白,第一反应往往是数据库出问题了,其实大部分时候问题在前面。我的排查顺序是固定的:设备端、网关端、消息队列、消费端、存储端,逐个对账。
先看设备端有没有上报。如果设备侧日志显示正常发,那就是网关或网络的问题;如果设备侧压根没发,那可能是采集程序挂了、传感器断线、或者信号弱重连中。这一步用最笨的办法最有效:拿一台设备单独抓包,看它实际往外发了什么。
如果消息队列里能查到数据,但数据库里没有,那就是消费端的问题。常见原因有三个:消费组位点提交逻辑写错(先提交后处理导致处理失败时数据丢失)、反序列化异常导致整批丢弃、以及消费线程被慢查询阻塞导致积压。这三个我建议分别在消费端加三个监控指标:位点滞后、反序列化失败计数、单条处理耗时 P99。
乱序问题往往更隐蔽,因为数据没丢,只是顺序不对。表现是算出来的时序曲线出现"回跳",或者某个小时的数据特别少、相邻小时特别多。这时要检查两件事:水位线是否设得太短导致迟到数据被丢弃;设备时间戳是否存在跳变。我遇到过一次,一批设备因为没有电池,断电重启后时间戳回到出厂时间,导致所有数据都被判定为严重迟到而进入侧输出,主链路看起来一切正常,但数据全进了隔离区。
提示:给侧输出(迟到数据)单独建一个可观测的计数指标。这个数字长期为零不一定是好事,可能说明你的水位线设得太宽松,实时性在悄悄变差;突然暴涨则一定是时间戳出问题了。
4.2 写入变慢与查询变卡:多半是基数和索引惹的祸
时序库的性能拐点通常不是数据量到了多少,而是序列数(不同标签组合的数量)涨到了临界值。几千个序列时怎么写都快,涨到几十万序列,每次写入都要更新大量索引,磁盘 IO 立刻打满。
排查方法是统计一段时间内不同标签组合的数量,看是不是有某个标签在快速膨胀。常见的膨胀源包括:把错误码、固件版本号、甚至自由文本当标签;设备重装后 ID 变了但没做映射,导致历史序列和新序列并存;以及临时测试设备接入了生产环境。
查询变卡的原因更集中一些。一是没带时间范围或者范围过大,扫了全表;二是聚合查询直接打在原始表上;三是返回结果集太大,把数据全拉到应用层再做计算。针对第三条,我的原则是能在库里算的绝不上拉到应用,平均值、最大值、分位数都交给数据库,接口只返回聚合后的几十行。
另外还有一个隐蔽的坑:时间范围边界。如果查询用的是开区间或者时区处理不一致,很容易漏掉整点数据或者重复统计。统一约定所有时间戳存 UTC、展示层再做时区转换,能避免绝大多数扯皮。
4.3 告警风暴:从根上解决而不是加更多规则
告警风暴的典型场景是:一台核心网关掉线,底下几百台设备同时失联,瞬间几千条告警涌出来,值班人员的手机直接被打爆,真正重要的那条反而被淹没了。
处理的思路是分层收敛。第一步做拓扑聚合,网关失联时,把它下属设备的离线告警统一收敛成一条"网关下 N 台设备异常",只发一条。第二步做根因抑制,明确优先级,网络层问题抑制设备层问题。第三步做聚合发送,把同一时间窗内的多条告警合并成一条摘要消息,而不是逐条推送。
还有一类误报是阈值抖动引起的,数值在阈值附近来回跳,告警就反复触发和恢复。这个用去抖能解决,但去抖参数要调。我一般要求连续三个采样点越限才触发,恢复则要求连续五个采样点在阈值内,形成不对称的滞回区间,效果比对称去抖好得多。
4.4 问题速查表
| 现象 | 优先怀疑 | 排查动作 | 处理方式 |
|---|---|---|---|
| 看板某时段空白 | 采集或消费中断 | 逐层对账设备、网关、队列、库 | 补数 + 位点校验 |
| 曲线出现尖刺 | 传感器异常值或重复数据 | 查质量位、查同时间戳重复 | 质量位过滤 + 幂等写入 |
| 写入延迟升高 | 序列基数膨胀 | 统计标签组合数 | 精简标签、合并序列 |
| 查询超时 | 扫原始表或范围过大 | 看执行计划是否命中分区 | 改查聚合表、强制时间条件 |
| 告警量激增 | 网关故障或阈值抖动 | 按设备分组看告警分布 | 拓扑收敛 + 滞回去抖 |
| 聚合表缺数 | 任务中断或水位丢失 | 查任务日志和断点记录 | 增量重跑 + 补数脚本 |
| 时间戳异常 | 设备时钟不同步 | 比对采集时间与接收时间 | 双时间戳 + 偏差隔离 |
5. 长期运营:成本、治理与边缘这三件事
系统上线只是开始,真正考验人的是跑了一年之后,成本涨了、数据乱了、需求变了的时候怎么办。
5.1 存储成本的三个抓手
成本控制我一般从三个地方下手,效果从大到小排列。
第一是上报策略优化。前面提过的变化上报能砍掉大量冗余数据,而且是在链路最前端砍,省的是全链路成本。我做过一次统计,把一批缓变点位从"固定五秒上报"改成"变化超阈值上报 + 五分钟心跳",数据量下降了六成多,而事后回溯分析所需要的信息一点没少。
第二是压缩与编码。时序数据大部分是浮点数且相邻值差异很小,用差分编码加压缩能拿到很高的压缩比。选型时要关注存储引擎的压缩算法是否可配,以及不同算法在压缩比和解压速度上的取舍。写入密集的场景可以选压缩快但比一般的算法,冷数据可以选压缩比更高的。
第三是分层与 TTL。热层保留时间不宜过长,七天到三十天足够覆盖绝大多数故障回溯场景。我见过把原始数据留一年的方案,成本翻了好几倍,实际查询命中率却不到百分之一。这个钱花得冤枉,不如把预算放在提升热层查询性能上。
5.2 数据质量治理:让它变成常规动作
数据质量在物联网项目里不是一次性工作,是长期脏活。我一般会建立几个常态化检查。
完整性检查:每个设备每小时的样本数是否达到理论值的 90% 以上,不达标的列出来。这个检查能第一时间发现采集异常,比事后人工看曲线靠谱得多。
合理性检查:数值是否在量程范围内,相邻两点的变化率是否超过物理可能。比如温度一分钟内跳了五十度,基本可以判定是异常值。这类数据不要直接删,标记质量位后保留,方便事后判断是传感器故障还是真有异常。
一致性检查:同一物理量的多个测点是否互相矛盾。比如进出口温度差为负、累计电量出现负增长,都说明有问题。这类检查需要业务知识,通常要跟现场工程师一起定义规则。
治理的产出不只是一堆报表,更重要的是把规则沉淀成校验任务,在数据入库时就跑一遍。早发现早隔离,比堆积半年后再清洗成本低太多。
5.3 边缘计算的合理边界
边缘计算这两年提得很多,我的看法是它能解决三类具体问题,除此之外没必要上。
第一类是带宽和延迟。高频振动的原始波形数据动辄每秒几兆,全传上云不现实也没必要,在边缘做特征提取(算均方根、峭度、频谱峰值)后只传特征值,数据量能降两三个数量级。
第二类是断网续传。现场网络不稳定,边缘节点需要有本地缓存能力,断网时把数据存本地,恢复后按时间顺序补传。补传的数据天然是乱序的,这又回到了前面说的水位线必须留够余量。
第三类是本地实时控制。有些保护逻辑要求毫秒级响应,走云端往返根本来不及,必须在边缘闭环。这类逻辑要和云端分析逻辑严格解耦,云端只负责下发策略和收集结果。
反过来说,如果只是为了"看起来先进"而在边缘堆一堆算力,最后运维成本翻倍、故障点变多,那就得不偿失。边缘节点的软件更新、日志收集、远程诊断能力,往往比算力本身更影响长期可用性,这一点在做方案时容易被忽略。
我个人在几个项目里的体会是,物联网大数据这件事,难的部分从来不是把某个组件的参数调到最优,而是一开始就把数据的脾气摸清楚——它有多快、有多脏、会怎么乱、谁在用、用完多久就可以扔。这几个问题想明白了,选型几乎是水到渠成的,反过来先定技术栈再去找场景,多半会在半年后推倒重来。另外一个小技巧:上线前一定要做一次至少七十二小时的压测,并且刻意制造乱序、重复和断网,看看链路的兜底逻辑到底管不管用。真到了生产环境,出问题的往往就是这些你当初觉得"应该不会发生"的地方。