

云端架构图再漂亮,也架不住厂区网络说断就断。
一个典型的工业 IoT 部署长这样——几十个分散的厂区/水电站/变电站,每个站点几百到几万台设备,现场传感器以毫秒级频率持续吐数据。如果把所有原始数据实时直传云端,带宽扛不住;如果只在云端做分析,网络一抖动,现场的实时告警和控制就全停摆。
这就是为什么工业 IoT 几乎必然走向云边协同:边缘负责实时处理和预处理,云端负责全局汇聚和深度分析。但"云边协同"这四个字背后,藏着一堆工程难题——数据怎么从边上到云上?网络断了怎么办?边和云各算什么?几百个边缘节点的逻辑怎么统一升级?
这篇就围绕 DolphinDB,把这些云边链路上的工程细节摊开讲。
先把"为什么需要云边"这件事讲透,不然后面的代码就只是配置堆砌。
问题一:带宽——原始数据全量上云不现实
一座大型水电站 200 多万个测点,每秒产生的原始数据动辄上 GB。把这些数据全部实时传到云端,专线带宽成本会是一个吓人的数字。而实际上,云端做全局分析、长期建模时,根本不需要毫秒级的原始波形——分钟级甚至小时级的聚合值就够用了。
所以边缘的第一职责是数据瘦身:把高频原始数据在本地聚合成低频特征,只把特征上云。原始数据留在边缘短期保存,供故障回溯用。
问题二:延迟——边缘要能本地实时决策
设备故障预警、产线联锁控制这类场景,对延迟的要求是毫秒级。如果每次判断都要"数据上云 → 云端计算 → 下发指令",端到端延迟往往在秒级,根本来不及。边缘必须能独立完成本地实时决策,云端只做"慢思考"。
问题三:可靠性——网络断了现场不能停
工业现场的网络远没有云端机房稳定。厂区专线可能被挖断、4G/5G 信号可能盲区、边缘节点可能短暂掉电。网络断了的时候,边缘的数据采集、实时告警、本地控制必须照常运行,断网期间产生的数据要在网络恢复后自动补传,不能丢。
这三个问题,分别对应了后面三节要讲的:边缘预处理(带宽)、分级计算(延迟)、断网续传(可靠性)。

DolphinDB 的边缘节点是一个完整的数据库实例,部署包只有几十 MB,能跑在工控机、边缘网关甚至树莓派级别的设备上。它和云端集群用的是同一套代码、同一套脚本——这一点很关键,后面会讲为什么。
边缘节点要做的第一件事,是把传感器原始数据做流式预处理,产出低频特征再上云。这里用 DolphinDB 的时间序列聚合引擎(createTimeSeriesEngine)做实时降采样:
// ========== 边缘节点 ==========
// 1. 接收传感器原始数据的流表(开启持久化,断网时不丢)
enableTableShareAndPersistence(table=streamTable(1:0,
`ts`deviceId`vibration`temperature`current,
[TIMESTAMP, SYMBOL, DOUBLE, DOUBLE, DOUBLE]), tableName=`sensorStream,
cacheSize=1000000)
// 2. 降采样输出流表(1 分钟聚合结果,上云用的就是它)
enableTableShareAndPersistence(table=streamTable(1:0,
`ts`deviceId`vibMean`vibMax`vibP95`tempMean`currentMean,
[TIMESTAMP, SYMBOL, DOUBLE, DOUBLE, DOUBLE, DOUBLE, DOUBLE]),
tableName=`aggStream, cacheSize=100000)
// 3. 时间序列聚合引擎:每 1 分钟窗口聚合一次
createTimeSeriesAggregator(
name=`edgeDownsample,
windowSize=60000, // 1 分钟窗口
step=60000, // 1 分钟步长
metrics=<[
avg(vibration), max(vibration), percentile(vibration, 95),
avg(temperature), avg(current)
]>,
dummyTable=objByName(`sensorStream),
outputTable=objByName(`aggStream),
timeColumn=`ts,
useSystemTime=false)
// 4. 原始数据订阅进来,喂给聚合引擎
subscribeTable(tableName=`sensorStream, actionName=`feedAgg,
handler=objByName(`edgeDownsample), msgAsTable=true)
几个工程要点:
enableTableShareAndPersistence 是边缘预处理链路的命脉。它把流表落到磁盘,断网期间原始数据会持续写入这个持久化流表,不会因为订阅端(云端)断开而丢失。这是后面断网续传的基础。windowSize 和 step 都是 60 秒,意思是每分钟产出一行聚合结果。1Hz 采样的原始数据,降采样后数据量缩减到 1/60;10kHz 的高频振动数据,缩减比例是 1/600000。边缘预处理把上云数据量压了几个数量级,带宽问题就这样解决了。useSystemTime=false 用数据本身的时间戳作为窗口依据,而不是系统时间。这在数据有延迟到达时更可靠。经过这一步,边缘节点持续产出的 aggStream 就是上云的对象——它是低频的、体量小的、信息密度高的特征数据。
接下来是云边链路的核心:边缘的 aggStream 怎么安全地传到云端集群。
DolphinDB 的做法是跨集群流订阅——云端集群主动订阅边缘节点的流表,边缘有新数据就推给云端。这比"边缘定时批量上传"更实时,又比"原始数据直传"省带宽。
// ========== 云端集群 ==========
// 1. 云端分布式表,存放所有边缘汇总上来的聚合数据
db = database("dfs://cloud", COMPO, [
database("", VALUE, 2026.01.01..2026.12.31),
database("", HASH, [SYMBOL, 20])
])
db.createPartitionedTable(table(1:0,
`ts`siteId`deviceId`vibMean`vibMax`vibP95`tempMean`currentMean,
[TIMESTAMP, SYMBOL, SYMBOL, DOUBLE, DOUBLE, DOUBLE, DOUBLE, DOUBLE]),
`siteAgg, `ts`deviceId)
// 2. 云端订阅边缘节点的 aggStream(跨集群,通过 host/port 指定边缘节点)
subscribeTable(
host="edge-site-01", // 边缘节点地址
port=8848,
tableName="aggStream",
actionName="collectFromEdge",
handler=tableInsert{loadTable("dfs://cloud", "siteAgg")},
msgAsTable=true,
reconnect=true, // 断线自动重连
offset=-1, // 订阅持久化流表时,从上次断点续传
filter=...) // 可选:只订阅特定 deviceId关键参数解读:
host / port:指向边缘节点。这就是"跨集群"的本质——订阅源不在本集群。reconnect=true:网络断开时自动重连,不用人工干预。工业现场网络抖动频繁,这个参数必须开。offset:控制订阅的起始位点。配合持久化流表,云端断线重连后能从上次消费的位置继续,不会漏数据也不会重读。这是断网续传的机制保障。每个边缘节点对应一个 siteId(站点标识),上云时打上站点标签。这样云端 siteAgg 表里就汇聚了所有站点的聚合数据,可以跨站点做全局分析。
云边协同方案里,80% 的故障都出在"网络断了怎么办"这一环。很多人 demo 时网络好好的,上线一遇断网就丢数据、重复数据、数据错乱。
DolphinDB 的断网续传能跑稳,靠的是三个机制配合:
机制一:边缘持久化流表兜底
前面边缘侧用 enableTableShareAndPersistence 把 sensorStream 和 aggStream 落了盘。这意味着即使云端订阅完全断开,边缘的数据采集和预处理照常运行,数据持续写入本地持久化流表。网络一恢复,云端从断点继续消费这些积压的数据。
机制二:订阅端的 offset 续传
云端订阅时配置 offset 续传。DolphinDB 的流订阅会记录消费位点,断线重连后从上次未消费的位置继续,而不是从最新位置(那会丢数据)或从头(那会重读海量历史)。
机制三:幂等写入 + 时间戳去重
断网恢复后补传的数据,可能和断网前最后几条数据在时间上重叠。云端写入时要按 (ts, siteId, deviceId) 做去重,避免重复。一种做法是云端表用 PKEY 引擎(主键唯一),天然避免重复;另一种是在写入逻辑里加去重判断。
// 云端用 PKEY 引擎存聚合数据,主键 (siteId, deviceId, ts) 保证幂等
db_pkey = database("dfs://cloudPkey", PKEY,
db1=database("", HASH, [SYMBOL, 20]),
pkKeys=`siteId`deviceId`ts)
db_pkey.createPartitionedTable(..., `siteAgg, `deviceId)
// PKEY 引擎下,重复主键的写入会自动覆盖而非追加,断网补传不会产生重复行这三个机制叠加,才能让"断网 → 边缘缓存 → 重连 → 补传 → 云端不重不漏"这条链路真正跑通。任何一个环节缺失,断网续传都会出问题——这是云边方案上线时最需要压测的地方。

云边协同不是简单地把数据从边缘搬到云端,而是要做一个计算分工。判断的依据是三个维度:实时性要求、算力需求、数据范围。

背后的逻辑很清楚:
边缘侧做实时预警的代码,和云端做全局分析的代码,用的是同一套 DolphinDB 脚本语法。这点很重要——它意味着你在边缘调试好的告警逻辑,可以原样搬到云端跑批量回溯,不用重写。这是"同一套代码"在云边场景下的实际价值。
// 这段预警逻辑在边缘(挂流引擎实时跑)和云端(挂批量SQL回溯跑)完全通用
def vibAlert(vibMean, vibP95, threshold) {
return iif(vibP95 > threshold & vibP95 > vibMean * 2.5, 1, 0)
}
// 边缘:挂响应式状态引擎,每分钟聚合结果进来就判断
// 云端:直接 select ... where vibAlert(vibMean, vibP95, 5.0) = 1云边协同还有一个容易被低估的难题:当你有几十上百个边缘节点时,怎么统一升级它们的处理逻辑?
如果每个边缘节点都要人工登录改脚本,运维成本会爆炸。DolphinDB 的解法是云端统一下发脚本:边缘节点启动时连云端拉取最新脚本,或者云端通过 rpc 主动推送更新。
// 云端:定义边缘要执行的处理逻辑(统一版本管理)
def edgeProcessingLogic() {
// 重建聚合引擎、订阅、告警规则
// ... 完整的边缘预处理逻辑
}
// 云端:把脚本推送到指定边缘节点执行(远程升级)
rpc(host="edge-site-01", port=8848, edgeProcessingLogic)
// 或者:边缘节点定时向云端拉取最新脚本版本
// 配合 scheduleJob,边缘每天凌晨检查并更新本地逻辑这种模式下,边缘逻辑的版本管理收敛到云端。你改一处,几百个边缘节点下次拉取就是新版本。这比"每个边缘节点维护一套独立脚本"可靠太多——后者几乎必然导致版本不一致、bug 难以复现的运维灾难。
需要权衡的是:远程下发脚本要求边缘节点能被云端访问到(反向也需要,因为数据订阅是云端拉边缘)。实际部署中,边缘通常在 NAT 后面,云端直接 rpc 过去可能不通,这时需要配合反向代理或让边缘主动拉取(pull 模式)而非被动接收(push 模式)。
最后一个工程话题:云边之间的数据一致性。
严格来说,云边架构做不到强一致——边缘和云端之间永远有网络延迟,断网期间数据差异更大。工业 IoT 场景下,务实的做法是接受最终一致,并明确几个边界:
// 边缘心跳上报(每分钟一条,超轻量)
def reportHeartbeat() {
insert into objByName(`heartbeatStream) values(now(), getHost(), getOS(), getVersion())
}
scheduleJob("heartbeat", "edge heartbeat", reportHeartbeat, * * * * *)
// 云端:超过 3 分钟没收到某边缘心跳,触发告警
select siteId, max(ts) as lastHeartbeat,
(now() - max(ts)) / 60000 as minutesSinceLast
from loadTable("dfs://cloud", "heartbeat")
group by siteId
having (now() - max(ts)) / 60000 > 3这种心跳机制是云边链路的"健康检查",能在边缘节点静默故障时及时发现,避免"数据悄悄丢了几天才发现"的严重事故。
客观说,云边协同不是所有 IoT 场景都需要的,几个边界要清楚:
把云边链路串起来看:
传感器 → 边缘持久化流表 → 时间序列引擎(降采样) → 边缘聚合流表
│
跨集群流订阅(reconnect+offset)
▼
云端分布式表(全局汇聚)
│ │
跨站点分析 长期建模/寻优
核心就几句话:
reconnect + offset 配合持久化流表,断网续传不丢不重。云边协同这件事,难的不是"数据能不能从边缘传到云端"——随便写个上传脚本都能传。难的是在网络不稳的工业现场,做到不丢、不重、不断、可监控。这几个"不"字背后,全是工程细节:持久化流表、offset 续传、幂等去重、心跳告警。把它们一个个落实,云边方案才能真正在生产环境跑稳。
参考链接
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。