3. 制造时序平台写入路径高可用

制造时序平台的写入路径,是设备数据从产线进入存储的第一道关口。它要同时承受高频采集、网络抖动、设备突发补传和下游存储抖动。写入路径的高可用,不是单点组件“不宕机”那么简单,而是要在消息队列、限流背压、失败重试和幂等保障四个环节上形成一条可恢复、可观测、可收敛的链路。本节围绕这条链路展开,先看整体数据流,再逐段说明关键实现。

制造时序平台写入路径高可用链路 设备采集端 OPC UA / MQTT 消息队列集群 Kafka 3 Broker + 副本 Topic: ts-raw (6 分区) acks=all, min.insync=2 写入网关 限流 + 背压 批量聚合 (500 点/批) 重试 + 幂等键 时序存储 TDengine / InfluxDB 按设备+时间分区 唯一键去重 背压信号:消费延迟 > 阈值时暂停拉取 批量失败 → 指数退避重试 (1s/2s/4s, 最多 3 次) 幂等写入保障 幂等键 = device_id + metric + timestamp(毫秒精度) 存储层唯一约束 + 网关侧去重缓存(TTL 10min) 死信队列 重试耗尽后转入 人工/定时补偿

消息队列选型与集群:先保证“不丢”,再谈“快”

制造时序写入的第一原则是数据不丢。消息队列承担削峰填谷和故障隔离的作用,选型时优先看持久化能力、副本机制和消费位点管理。Kafka 是常见选择,因为它支持分区顺序写、多副本同步和消费者组重平衡。一个可参考的集群配置是 3 个 Broker,Topic 设置 6 个分区、副本因子 3,生产者端设置 acks=all、retries=5、enable.idempotence=true,并在 Broker 端设置 min.insync.replicas=2。这样即使一台 Broker 宕机,只要剩余两台同步副本在线,写入仍可继续,且不会因为副本不足而静默丢数据。

分区数不是越多越好。分区过多会增加 Broker 元数据压力和消费者重平衡时间。一般按“峰值写入吞吐 ÷ 单分区可承载吞吐”估算,再留 1.5 倍余量。例如单分区稳定写入约 8 MB/s,峰值总写入 30 MB/s,则 6 个分区足够。消费者组内消费者数量不应超过分区数,否则多出的消费者会空闲。

写入限流与背压:让系统在过载时“慢下来”而不是“垮掉”

限流解决的是入口过载,背压解决的是下游过载。写入网关通常采用令牌桶限流:按设备类型或租户分配令牌速率,例如每条产线 5000 点/秒,突发容量 10000 点。当令牌不足时,网关可以选择短暂排队或直接拒绝并返回可重试状态码,而不是无限缓冲导致内存溢出。

背压则从消费端反向传递。网关消费 Kafka 时监控消费延迟(Lag),当 Lag 超过阈值(例如 10 万条)或存储写入 P99 超过 200 ms 时,主动降低拉取速率或暂停拉取,让 Kafka 中的消息堆积作为缓冲。这样存储层不会被打穿,恢复后又能快速追平。背压信号必须可观测,建议暴露 write_lag、batch_queue_size、backpressure_active 三个指标。

批量写入失败重试:区分可重试与不可重试

批量写入失败的原因很多:网络超时、存储节点短暂不可用、批次过大导致超时、数据格式错误。重试策略必须区分对待。网络超时和节点不可用属于可重试错误,采用指数退避,例如首次 1 s、第二次 2 s、第三次 4 s,最多 3 次;批次过大则应该拆分后重试,而不是原样重发。数据格式错误属于不可重试错误,直接转入死信队列并告警,避免无效重试拖垮链路。

重试还要控制并发。如果大量批次同时失败并同时重试,会形成重试风暴。建议在网关内维护一个重试队列,限制同时重试的批次数(例如不超过 20 个),并给重试批次设置独立的超时时间。重试成功后要记录补偿日志,便于核对数据完整性。

幂等写入保障:重试不产生重复数据

重试必然带来重复写入的风险。幂等写入的核心是让同一批数据无论写多少次,结果都一致。实现方式分两层:第一层在网关侧生成幂等键,通常由 device_id + metric + timestamp 组成,时间戳精确到毫秒;第二层在存储侧建立唯一约束或使用 upsert 语义。例如 TDengine 中可以利用时间戳主键和标签组合实现覆盖写,InfluxDB 中相同 measurement、tag set 和时间戳的写入会覆盖旧值。

网关侧还可以维护一个短 TTL 的去重缓存,例如 10 分钟内已成功写入的幂等键集合。重试前先查缓存,命中则直接跳过。缓存容量按峰值写入速率乘以 TTL 估算,若峰值 5 万点/秒、TTL 10 分钟,则约 3000 万个键,需要评估内存或改用布隆过滤器。对于制造场景,设备时间戳可能重复上报,建议在采集端就补充序列号或批次号,避免不同数据被误判为重复。

幂等键中的时间戳建议使用设备采集时间而非网关接收时间,否则同一数据在重试时接收时间变化会导致幂等失效。若设备时间不可信,可退化为“设备时间 + 序列号”组合。

链路协同与故障收敛

四个环节不是孤立的。消息队列副本不足时,生产者应快速失败并触发告警;限流触发时,背压应同步生效,避免消息在网关内存中堆积;重试次数耗尽后,数据进入死信队列,由补偿任务在存储恢复后重新写入,补偿任务同样要遵守幂等规则。整条链路的健康判断可以看三个信号:Kafka 写入成功率、网关背压激活时长、死信队列增长速率。若写入成功率低于 99.9%、背压持续超过 5 分钟或死信队列持续增长,就说明写入路径高可用已经退化,需要按“队列—限流—重试—幂等”的顺序逐段排查。

实际部署时,建议把写入网关做成无状态多实例,配合消费者组实现故障自动转移;Kafka 跨机架部署副本;存储层按设备分组分片,避免单节点热点。这样即使某个环节短暂失效,数据仍能在队列中等待,恢复后按幂等规则补写,最终达到“不丢、不重、可追平”的目标。