场景二 · 车联网 / IoT
高并发场景 · Scenario 02

场景二:车联网 / IoT 数据平台

如果说秒杀是"百米冲刺",IoT 就是"永不停歇的马拉松":百万台车每秒都在上报位置、车速、电池状态,写入洪流 7×24 小时不退潮,存储账单还蹭蹭上涨。

持续高压写 时序天性 冷热分层 海量存储
100万+在线设备数(中型车企)
百万点/秒持续写入速率
TB/天新增数据量
99:1写读比(写远大于读)
📑 本页目录
01

场景描述与业务特征

每辆智能汽车就像一个话痨:每 1~10 秒上报一次 GPS、车速、电机温度、电池 SOC……单车每天产生数万条数据。一家有 100 万台在网车辆的车企,平台每秒要接住几十万到几百万个数据点。类比:不是一群人挤一扇门(秒杀),而是一百万根水管同时对着你的水库放水,全年不关阀

写入 时间 → 普通业务系统的日常水位 持续高位运行,没有"低谷喘息期"(早晚高峰还会再抬一截)
持续型流量:不是"能不能扛住一秒",而是"能不能扛住每一秒" —— 拼的是吞吐、成本和稳定性。

🌊 写多读少

数据 99% 的时间在"睡觉",只有查轨迹、出报表、诊断故障时才被读。为写优化是第一原则。

⏱️ 时序天性

每条数据都带时间戳、按时间追加、极少修改。天生适合时序数据库(按时间分区、列式压缩)。

📦 单条小、总量大

一条报文几百字节,但架不住量大:1TB/天起步,存储成本是核心 KPI。

🔌 弱网乱序

车过隧道、进地库就断网,恢复后补传旧数据——数据到达顺序和产生顺序经常不一致。

🔁 至少一次送达

设备端重试机制导致同一条数据可能被发两次,平台必须自己去重。

🚨 实时+离线双需求

既要实时告警(电池过热 3 秒内通知),又要离线分析(月度驾驶行为报告),一份数据两条处理链路

02

整体运作流程

IoT 平台的标准姿势是"接入 → 缓冲 → 分流 → 分层存储":网关只管接得快,Kafka 当巨型蓄水池,后面实时、离线两条流水线各取所需,最后按数据温度分层存放。

🚗 百万设备 MQTT / TCP 长连接 1~10秒/次上报 断网补传 接入网关集群 EMQX/自研网关 鉴权·解码·薄处理 只做转发不做业务 Kafka 蓄水池 按 vin 分区保序 削峰 + 多方订阅 留存7天可回放 ⚡ 实时流处理 Flink:告警规则 去重·乱序水位线 🕐 批量写入 攒批 5000 条/次 顺序写时序库 📊 离线数仓 Spark/Hive T+1 报表·模型训练 🔥 热 Redis/内存表 最新状态·告警 🌡️ 温 时序库 3~6月 轨迹·近期查询 🧊 冷 对象存储/湖 合规归档·极便宜 核心思想:接入与处理解耦,一份数据多路消费,按"温度"分层存放省钱
🧠
为什么 Kafka 是灵魂?它把"设备上报速度"和"下游处理速度"彻底解耦:下游挂了、慢了,数据先在 Kafka 里躺着(可回放);新增一个消费方(比如新上线的告警系统)也不用动接入层。顺序写磁盘 + 分区并行让它单集群轻松扛百万级 TPS。
03

核心瓶颈与数据一致性挑战

🕰️ 乱序:迟到的数据算不算数?

车辆 10:00 过隧道断网,10:05 恢复后补传 10:00~10:05 的数据。此时"10:00~10:05 平均车速"的统计窗口早关了。Flink 水位线(Watermark)就是给迟到数据留的宽限期:窗口多等 N 秒再关账。等太久实时性差,等太短数据不准——又是取舍。

👯 重复:至少一次的副作用

设备发出报文没收到 ACK 就重发,平台可能收到两条一模一样的数据。里程统计、电费计算会虚增。解法:以"设备ID+时间戳+序列号"做唯一键去重,或选支持 upsert 的时序库让重复写入天然幂等。

💾 写入放大:数据库被"逐条写"拖死

百万点/秒逐条 INSERT,任何数据库都会跪——每条都要走一遍网络、解析、索引、刷盘。攒批写入(每 5000 条或每 200ms 刷一次)能把开销摊薄百倍,代价是数据可见性延迟零点几秒。

💰 存储成本:不删数据会破产

1TB/天 × 365 天 × 3 副本 ≈ PB 级。全放 SSD 时序库,存储账单能吓哭 CFO。必须冷热分层 + 降采样(3 个月前的数据从秒级抽稀成分钟级)+ 列式压缩(时序数据压缩比可达 10:1 以上)。

💥
事故现场还原:某车企促销活动 OTA 升级,百万台车同时重连、同时全量补传离线数据,瞬时流量翻 8 倍打崩接入层,连锁压垮 Kafka 消费延迟 4 小时——设备端"随机退避重连 + 补传限速"必须在协议里就设计好,等出事再改,车已经在路上了。
04

优化手段、获益与代价

① MQTT 网关集群 + 薄接入 接入层

网关只做鉴权、解码、转发三件事,不写数据库不做业务,无状态水平扩容。

✅ 获益:单节点数十万连接,扩容只需加机器;业务变更不动接入层。
⚠️ 代价:多一跳转发延迟;网关集群本身的连接均衡与会话迁移要额外设计。

② Kafka 缓冲 + 按设备分区 核心

所有数据先进 Kafka,按 vin(车架号)哈希分区,保证同一辆车的数据在分区内有序。

✅ 获益:削峰、解耦、可回放三合一;单车数据局部有序,简化下游乱序处理。
⚠️ 代价:端到端延迟增加百毫秒级;Kafka 集群本身的容量规划与运维成本;分区数一旦设小,扩分区会打乱有序性。

③ 批量写入 + 时序数据库 存储

消费端攒批(如 5000 条/200ms)写入 TDengine / InfluxDB / Apache IoTDB,按时间+设备分区,列式压缩。

✅ 获益:写入吞吐提升 10~100 倍;压缩比 10:1 起步,存储成本大降;时间范围查询飞快。
⚠️ 代价:数据可见延迟亚秒级;攒批进程崩溃可能丢一小批(需 Kafka 位点重放兜底);时序库对复杂关联查询不友好。

④ Flink 流处理:水位线 + 状态去重 一致性

用事件时间 + Watermark 容忍乱序,用 keyed state 记录已见序列号去重,checkpoint 保证 exactly-once。

✅ 获益:迟到数据不丢、重复数据不重算,统计结果可信;告警秒级触达。
⚠️ 代价:状态后端占内存/磁盘;水位线延迟拉长实时性;Flink 作业的调优与运维门槛不低。

⑤ 冷热分层 + 降采样 成本

热数据(7天)SSD 时序库,温数据(6个月)降采样后存 HDD,冷数据转对象存储(S3/OSS)只为合规留存。

✅ 获益:综合存储成本降 70%+,热查询性能不受海量历史拖累。
⚠️ 代价:跨层查询体验割裂(查半年前轨迹要等几秒);降采样丢失细节,事故回溯可能不够用——留存粒度要和法务/安全团队对齐。
🛡️
降级策略:① 洪峰超限 → 网关按数据优先级丢弃(先丢车机娱乐埋点,死保安全告警类报文);② 时序库写入积压 → 自动拉大攒批窗口、非关键指标降频;③ 设备端配合 → 下发指令降低上报频率(10秒/次 → 60秒/次)。IoT 的三角站位:性能+可用性优先,接受"秒级最终一致"。
05

多种解决方案对比与选型建议

存储方案写入吞吐压缩/成本查询能力适用规模
MySQL 分表
按月分表硬扛
低 · 万级/秒SQL 灵活万台设备以内的试水期
MongoDB
文档模型+TTL索引
中 · 十万级/秒较灵活报文结构多变的中小平台
时序数据库
TDengine/InfluxDB/IoTDB
高 · 百万级/秒优 · 10:1+时间维度极强十万~百万设备的主流选择
HBase/Cassandra
宽表 LSM 存储
高 · 百万级/秒只适合按键查超大规模+自有大数据团队
数据湖方案
Kafka→Iceberg/Hudi+OLAP
高(批流一体)优 · 对象存储价分析能力最强分析需求重于点查的平台
🎯
选型口诀:万台以内 MySQL 分表先跑起来别过度设计;设备上十万,Kafka + 时序数据库是性价比之王;报文字段天天变选 MongoDB 换开发效率;分析报表是主战场就直接建数据湖。记住 IoT 的钱大头在存储——选型先算三年存储账单,再看性能参数
06

推演检验:换个条件还成立吗?

背下架构图不算学会,能判断"条件变了方案还成不成立"才算。先自己推,再展开参考。

推演 1:如果百万台车从"秒级定时上报"改成"仅报警时上报"(事件驱动),Kafka + 时序库这套还需要吗?

💡 参考推演

日常写入量骤降几个数量级,时序库可以退化成普通库分表。但注意事件驱动的风险是相关性脉冲:台风天全城车辆同时报警、OTA 升级后全量回传日志——瞬时峰值可能比定时上报更猛。所以 Kafka 这层缓冲反而更不能省:定时上报的流量可预测,事件驱动的流量不可预测,越不可预测越需要队列兑底。

推演 2:如果新业务要求"查车辆当前位置"毫秒级响应(网约车派单),攢批写入还成立吗?

💡 参考推演

成立,但要读写路径分离:攢批只影响"历史轨迹落库"的延迟,而"当前位置"应该在消费链路上顺手更新一份 Redis 里的 last-known 状态(每车一个 key,覆盖写)。查实时位置读 Redis,查历史轨迹读时序库——同一份数据两条链路,各自优化各自的延迟,而不是逼落库链路提速。

推演 3:如果存储预算砍半,三年账单撑不住,优先动哪一层?

💡 参考推演

先谈数据生命周期而不是换数据库:热数据(近30天)保留秒级精度;温数据降采样成分钟级聚合(体积缩几十倍);冷数据归档对象存储甚至删原始报文只留聚合结果。大部分 IoT 分析只用聚合值,原始报文的"全量永久保存"往往是惯性而非需求——先把需求问清楚,再动架构。