ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

智能家居数据存储升级:从MySQL到分布式架构的完整实践

智能家居数据存储升级:从MySQL到分布式架构的完整实践 做智能家居项目这几年最让我意外的不是设备联动逻辑有多复杂也不是 App 开发有多磨人而是存储——当一套全屋智能真正跑起来之后数据量增长的速度远超预期传统单机方案会在某个毫无防备的晚上直接崩给你看。这篇文章想聊的是我把智能家居数据存储从“MySQL NAS”的单机架构升级到大数据领域分布式存储架构的完整过程。包括数据分类与选型、端到端的数据链路设计、数据模型与分区策略、集群部署与运维以及家庭场景下成本和隐私的平衡。如果你正在做智能家居系统、物联网平台或者刚接触大数据想找一个落地场景练手这篇文章应该能给你一套可以直接参照的思路。开销先想清楚数据是怎么变大的再谈架构怎么设计。1. 全屋数据增长起来后最先崩溃的往往是存储1.1 数据量是怎么悄悄涨上来的很多人对智能家居数据的感知是“不就是几个传感器吗能有几个字节”真做了才知道数据量比想象中大得多。我列一个典型全屋智能场景的估算4 路监控摄像头每路 2Mbps 码流24 小时不间断录制一天约 86GB。只做移动侦测录像会少一些但关键区域全时段录制非常常见。50 个无线传感器温湿度、门窗磁、人体存在、烟雾、燃气、水电表每 15 秒上报一次一天约 28.8 万条记录。智能门锁、开关面板、情景模式产生的操作事件一天也有几千到上万条。再加上设备心跳、运行日志、固件版本信息。这还只是单户家庭。如果是公寓、社区、酒店这类多户场景数据量会直接乘以户数。一套 200 户的公寓智能系统一个月产生的数据量基本就是 TB 级。这个量级已经不是随便找个 MySQL 或者 NAS 就能扛住的了。1.2 智能家居数据与传统业务数据的本质区别最开始我也犯过懒想着“数据不多MySQL 表建好就行”。但智能家居数据的特征和传统 Web 业务数据差别太大了写入频率极高设备是持续上报的不是用户操作驱动的低频请求天然就是每秒几十到上千条写入。时序特性极强几乎每条记录都带时间戳最常见的查询是“某设备在某个时间段内的曲线”而不是随机的点查。冷热分布极端昨天的数据可能还在被频繁查看一周前的几乎没人碰三个月前的想不起来看。但原始数据又不能随便删。写多读少、几乎没有更新这和电商、交易这类业务完全不同它基本没有 update 需求。数据形态杂既有几百字节的传感器读数也有几 GB 的视频文件还有几十 KB 的抓拍图片形态差异大到没法用一套存储统吃。这类数据如果硬塞给面向“用户、订单、交易”设计的传统关系型数据库就好比拿轿车去拉矿不是不能跑而是跑不远。1.3 单机存储为什么扛不住一次真实的容量危机我踩过这个坑记忆非常深。项目初期是一套 30 台设备的小规模试点后端用 MySQL视频直接丢 NAS。前三个月一切正常半年后问题开始密集出现MySQL 里的传感器表到了几千万行普通查询从几十毫秒变成几秒。加索引效果也有限因为写入太频繁索引维护本身就在拖慢入库。表文件占掉了磁盘 200 多 GB备份一次要跑一晚上。后来做了分区才勉强维持。NAS 的硬盘空间平均每周涨 50GB 左右换大盘、清空间变成了每周固定工作。说实话单机方案不是不能用而是它把问题往后推了。数据量翻三倍、翻五倍的时候单机方案只能靠加硬盘、升配置、拆库而这些操作很快就会碰到物理上限。我当时想明白了一件事智能家居的存储问题本质是海量时序数据 海量文件的存储问题这个问题的标准解法在大数据领域不在传统 Web 架构里。所以后来才彻底转向了分布式存储的思路。2. 选型不是选最火的而是按数据分类去匹配2.1 先把智能家居的数据分成四类选型之前先做数据分类。我的经验是按“数据形态 访问模式”来分而不是按“业务模块”分。智能家居场景里大概有四类数据数据类别典型例子数据形态访问特点高频时序数据温湿度、人体感应、能耗、设备状态几百字节/条的小记录高频写入、按时间范围查询中低频事件数据门锁开关、告警、情景触发结构化文本查询频率较高需要精确过滤流媒体/文件数据监控视频、抓拍图片、升级包几MB到几GB的文件顺序写、随机读关系型元数据用户信息、设备台账、联动配置典型的表结构事务性读写分完类选型思路就清晰了不要试图用一种数据库解决所有问题。大而全的方案往往处处妥协。2.2 高频时序数据优先考虑物联网时序数据库高频时序数据是这个场景里最核心、量最大的一类。候选方案有三个TDengine、InfluxDB、TimescaleDB。我最终选了 TDengine主要理由是专为物联网设计超级表 子表模型天然匹配“一类设备一张模板、每台设备一条子表”的场景。传感器建模比 InfluxDB 的 measurement tag 模型更直观。开源版自带集群能力这对预算有限的项目很重要。InfluxDB 的集群能力在开源版里是缺失的单机撑到规模上限之后会比较被动。存储和查询效率高列式存储、内置压缩、按时间自动分片对时序场景优化很深。实测同场景下占用空间比 MySQL 小非常多。部署运维相对简单一个安装包、几条命令就能起服务对中小团队很友好。InfluxDB 我也用过。生态成熟、文档丰富1.x 的 InfluxQL 很好上手但 2.x 之后 Flux 查询语法学习曲线有点陡。如果你只是想单机跑一套小规模智能家居InfluxDB 完全够用只是后续扩容要提前想好。TimescaleDB 适合已经重度使用 PostgreSQL 的团队。它本质上是 PG 插件SQL 完整迁移成本低。但它在这类场景里更像“能跑时序的 PG”而不是真正的分布式时序系统跨节点扩展需要手动分表和分区运维复杂度反而上去了。2.3 流媒体与文件数据对象存储是更稳妥的归宿视频和图片这块有朋友问过我为什么不上 HDFS。我的回答是HDFS 的核心场景是海量文件的批量处理它对小文件非常不友好——NameNode 内存会被大量小文件元数据吃光。而智能家居里的抓拍图片动辄几万张单张可能不到 100KB硬塞 HDFS 等于给自己挖坑。对象存储才是这个场景的主流解。二选一的话MinIO轻量、S3 兼容、部署超级简单社区活跃适合中小项目和家庭场景。我试过在树莓派上跑也没问题。Ceph功能全面支持块存储、文件存储、对象存储但架构复杂、运维成本高。没有专业运维团队的话建议别碰。对象存储真正要注意几件事一是小文件合并抓拍图片单张体积小可以在网关层做批量合并再写入二是桶生命周期规则旧视频自动转归档或删除三是访问控制视频文件不能公开读要用预签名 URL。2.4 关系型元数据不要为了分布式而分布式用户信息、设备台账、场景联动配置、告警规则的量都很小事务要求却很高。这类数据我的建议是继续用 MySQL 或 PostgreSQL做主从或快照备份就够了。硬要把这堆数据拆到分布式 KV 或 NewSQL纯属自找麻烦。但有一个例外如果你做的是 SaaS 平台要服务几十万用户元数据也会膨胀那时候可以考虑 TiDB 这类 NewSQL。它兼容 MySQL 协议分布式扩展对开发侧侵入小。中小项目前期完全用不上。2.5 一张选型对比表数据类别推荐主选备选不建议高频时序数据TDengineTimescaleDB / InfluxDB 单机直接上 HBase开发成本高事件类数据时序库 / ESES 索引方案放业务 MySQL 大表流媒体文件MinIO云 OSS/COSHDFS小文件坑关系元数据MySQL / PostgreSQLTiDB单独搭一套 MongoDB3. 一条完整的分布式存储链路从设备端到存储集群3.1 设备端先落盘再上报断网不能丢数据分布式存储做得再好如果设备端的数据上不来一切都是白搭。智能家居设备经常挂在不太稳定的 WiFi 上或者被直接断电。我的设计原则是“设备本地先落盘网络恢复再补报”。简单可靠的方案是设备端用 SQLite 做环形缓冲传感器采集数据先写入本地 SQLite用一个固定容量的循环表写满后自动覆盖最旧数据。上报线程按批次从 SQLite 读数据通过 MQTT 发布到网关。上报成功就删除已上报记录失败则保留并重试。网络断开时数据留在本地恢复后自动追平。这个方案要求设备端有一点存储空间但对现代物联网芯片来说几百 MB 的 Flash 完全不是问题。好处是链路里任何一环抖动原始数据都不会丢。3.2 网关汇聚层统一协议、统一时间、去重网关这层不少方案会忽略直接让设备对接到后端。但我建议中间至少要有一层汇聚和规整原因有三协议众口难调厂商 A 的设备走 MQTT厂商 B 走私有 TCP厂商 C 走 Zigbee 网关桥接。到汇聚层统一转为标准 JSON 消息后面的事情才简单。时间戳必须统一很多设备本地时钟不准有的差几秒有的差几分钟。时间戳不统一时序数据就乱了。网关层根据接收时间校正设备时间戳把误差控制在秒级。去重与幂等设备端重试机制可能产生重复消息网关层维护一个最近消息 ID 去重集合Redis 里做一个简单 set保证下游只接收一次。在这层我还会顺带做字段规整把不同设备的指标名称统一成一套标准比如温度都叫temperature湿度都叫humidity。这套标准命名到了存储层就是建表结构提前定好能省掉后面大量清洗工作。3.3 消息队列削峰填谷别让存储集群被瞬时流量打崩设备数据直接写存储集群行不行规模小的时候可以规模上来之后不行。典型场景是每日定时任务早上 7 点智能家居平台自动触发“起床模式”几十上百台设备几乎同时上报状态瞬时写入可能是平时的 5 到 10 倍。消息队列在这一层的作用就是削峰填谷。我的链路里是这样用的网关汇聚后的消息先投递到 Kafka。存储集群的写入端以稳定速率消费消息批量写入存储。消息队列同时充当缓冲层即使存储集群短暂抖动或重启消息也不会丢。推荐 Kafka 是因为它在高吞吐消息场景下最成熟。但如果你团队没有专门的运维人员Kafka 的运维成本确实略高可以考虑用 EMQX 内置的持久化能力代替或者在数据量不大时直接用 Redis Stream 撑一下。灵活选型的前提是链路职责要清晰。3.4 存储写入批量写入和分区是吞吐量的关键真正写入存储集群时几个细节对性能影响非常大批量写入单条写入和批量写入的吞吐差距可能在一个数量级。以 TDengine 为例每条 SQL 里带多行 values或者走参数绑定接口写入吞吐能提升好几倍。按设备哈希分布如果要写入多个分片按设备 ID 做哈希保证同一设备的数据落在同一个分片避免跨节点传输。写入线程池调优消费线程不是越多越好要结合存储节点的 CPU 核数和磁盘 IO 能力做压测找到最优并发数。幂等设计写入失败重试时依靠“时间戳 设备ID”做唯一键约束防止重复数据。这一层的目标只有一个让存储集群以稳定、持续的状态接收数据不被瞬时脉冲打乱节奏。4. 数据模型与分区设计决定分布式存储性能的核心4.1 一张能打的数据表以 TDengine 超级表为例数据模型的优劣对分布式存储性能的影响有时候比集群规模还大。以 TDengine 为例我的传感器表结构长这样CREATE STABLE sensor_data ( ts TIMESTAMP, value FLOAT, quality TINYINT ) TAGS ( device_id NCHAR(32), sensor_type NCHAR(16), location NCHAR(32) );这套“超级表 子表”模型的核心思想是用 TAGS 描述设备的静态属性用列描述动态采集值。每个设备一张子表存储引擎天然把同一设备的数据放在一起。查询“某设备某时间段的曲线”时只需要扫一个设备的数据块速度和效率都非常高。反过来如果我把所有设备的数据硬塞进一张大表然后靠 device_id 索引去查那正是当初 MySQL 卡死我的原因。分布式时序系统的设计哲学是“先按设备/标签把数据物理隔离再查询”和传统关系库的“先混在一起再靠索引捞”完全不同。4.2 预分区与分片策略避免数据热点数据进了分布式集群如果分布不均匀热点节点就会拖垮整体性能。我的经验是TDengine 在创建库的时候指定 vgroups 数量一个 vgroup 内部自动管理数据分布。智能家居场景建议按“设备规模 / 50 万条每分片”来估算 vgroups。如果非要上 HBase行键设计非常关键。自增 ID 一定会造成热点写正确做法是把设备 ID 反转后拼上时间戳让连续写入分散到不同 Region预分区时再按 rowkey 范围切好 Region。对对象存储 MinIO 来说分区不是核心问题但要按业务维度规划桶结构比如/tenant/{household}/video/YYYYMM/这种路径既方便生命周期规则管理也方便权限控制。预分区的原则一句话写之前先想好数据怎么分千万别等数据堆上去之后再做重分布那会是一场噩梦。4.3 压缩与编码时序数据的空间账本时序数据有天然的规律性相邻两条记录时间间隔固定、数值变化幅度小。这种规律让时序数据的压缩比非常高。以我自己的实测数据为例原始传感器数据大约能压缩到原来的 10%~20%也就是说 100GB 的原始数据在时序库里可能只占 15GB 左右压缩比远超关系库。具体编码上也可以利用数据特点浮点型传感器值用差值 异或编码Gorilla 算法压缩率很高。整数型状态值用差值 变长编码。时间戳统一精度比如都用毫秒不要混用秒和毫秒否则压缩效果会打折。对象存储里的视频文件不建议做二次压缩因为视频本身就是高度压缩的格式再压收益极低还浪费 CPU。视频存储省钱的核心靠“存多久”和“存几份”不是靠压缩。4.4 TTL 与数据生命周期该删的别舍不得很多项目做完存储架构最后死在没有生命周期策略上——数据无限增长磁盘很快见底。我在每个智能家居项目里都会提前定好一套保留策略数据级别保留时长存储位置说明传感器原始明细1~3 个月时序数据库之后靠聚合数据支撑5 分钟/1 小时聚合数据1~3 年时序数据库长期趋势和月报用事件日志6 个月时序库 / ES异常追溯用视频文件7~30 天对象存储按事件标记的可以更长抓拍图片30~90 天对象存储报警取证用TTL 在 TDengine 里可以直接在创建库时指定KEEP参数过期时间一到数据自动删除。MinIO 则通过桶生命周期规则实现对象过期删除。这套策略跑起来之后存储增长率会从一开始的线性增长变成有界增长磁盘再也不会无声无息地爆掉。5. 集群部署与运维实战不上生产不知道的那些坑5.1 先算清楚容量和规模再买机器部署集群的第一步不是装软件而是做容量规划。给一个我常用的估算模板以一套服务 1000 户的智能社区平台为例每户假设有 30 个传感器设备每 30 秒一条记录。单户每天约 8.64 万条1000 户就是 8600 万条/天。按每条记录 100 字节算一天原始数据约 8.6GB保留 90 天约 774GB。时序库压缩比按 20% 算实际占用约 155GB3 副本约 465GB。视频按每户每天 1GB 事件视频、保留 7 天算1000 户共约 7TB 原始2 副本约 14TB。这个量级下一套 3 节点时序集群 3 节点 MinIO 集群每节点 8 核 / 64GB / 4TB 盘基本够用。但容量规划不能只看总量还要看峰值全屋定时唤醒场景的瞬时写 QPS 可能是平时的 10 倍集群的 CPU 和网络要按峰值预留 30% 余量。5.2 副本数到底选几份分布式存储里的副本数是个容易被低估的决策。我的底线是 3 副本2 副本在多数系统里是“伪安全”如果一个节点挂了另一个节点还有完整副本但此时集群已经没有能力承担新的故障恢复期间一旦再出问题就可能丢数据。3 副本可以容忍 1 个节点故障同时在故障期间还有冗余能力。预算真的紧张时可以考虑 2 副本 异机定时备份至少保证物理介质损坏时有第二份数据可用。副本数和节点数要匹配3 副本至少要 3 个存储节点否则副本全落在同一台机器上等于没有副本。5.3 机器与磁盘选型钱要花在刀刃上时序数据库是 CPU 和 IO 密集型应用压缩和查询都吃算力。我的选型经验是CPU8 核起步16 核更好。TDengine 的 vgroup 数量最好与 CPU 核数匹配。内存能上 64GB 就不要省。内存被查询缓存、元数据和排序吃掉了内存不足时查询会频繁落盘性能断崖式下跌。磁盘热数据用 NVMe SSD温数据用 SATA SSD冷数据用大容量 HDD。不要把日志和数据放同一块盘。网络节点间复制数据的流量很大千兆不够至少要万兆或做多网卡绑定。WiFi 不应出现在存储节点链路里。还有一个坑集群里所有节点必须统一时区并保持时间同步否则分布式一致性检查会频繁报错数据也可能因时间偏移被判为乱序。我用 chrony 统一做 NTP 配置上线前专门检查一轮。5.4 部署配置里最容易被忽略的几项我把最近一次部署的配置经验整理一下这些都是踩过坑之后才真正重视起来的东西Linux 打开文件数限制ulimit -n存储节点默认 1024 远远不够我调到 65535 以上否则并发连接一高就报“too many open files”。vm.max_map_count不少存储组件对内存映射区域数量有要求默认值偏低会导致启动失败。TCP 缓存和 backlog网络层不加参数万兆网卡跑不到预期吞吐。存储目录权限和数据盘挂载参数建议用 XFS 或 ext4挂载参数加noatime减少不必要的元数据写入。数据盘和日志盘分离日志写满磁盘后如果和数据盘共用挂载点会直接拖垮核心存储服务。这些配置看着琐碎但任何一个没到位都可能在上线后某个半夜变成线上事故。我习惯把部署参数固化成脚本每次新节点直接跑一遍不再手工调。6. 冷热数据分层与查询加速海量数据也能看起来很快6.1 把数据分成热、温、冷三档来存数据量一大如果所有数据都放在同一套高性能存储里成本会很浪费。我的做法是把数据分成三档热数据最近 24 小时的数据。App 实时页面、告警联动都在查这部分放在内存缓存或 NVMe 盘上保证毫秒级响应。温数据过去 1~3 个月的数据。报表、周月趋势、人工追溯时会查放在普通 SSD 或 HDD 上允许查询时间在几百毫秒到几秒。冷数据3 个月以上明细。极少访问主要用于审计和长期统计直接归档到对象存储或低成本冷存储。在 TDengine 里可以按日期做分区配合多级存储管理温冷数据MinIO 则用桶生命周期把旧对象自动迁移到低频存储。这套分级做完高性能存储上的空间占用大幅下降成本曲线明显被压平。6.2 缓存与预聚合让常用查询提前算好查询性能优化里性价比最高的手段不是加索引而是预聚合。我的平台上有三类常用查询首页实时卡片当前温湿度、用电功率等。历史曲线过去 24 小时、7 天、30 天的趋势。报表统计月度用电量、离家时长、告警次数。如果每次都去扫明细表数据量一大响应就慢。我做了两层优化Redis 缓存最近查询结果key 用“设备ID 查询维度 时间粒度”过期时间 30 秒到 5 分钟首页类查询直接从缓存返回。预聚合表在 TDengine 里用连续查询Continuous Query每 5 分钟、每小时、每天生成一次聚合数据分别落到独立聚合表中。查历史曲线时直接查聚合表不回扫明细。一个实测对比优化前App 端查看 7 天温度曲线查询耗时 3 秒多优化后走聚合表加缓存耗时降到 200ms 以内体感上是秒开。6.3 大屏和 App 查询的约束策略和很多人想的不同查询慢很多时候不是存储不行而是查询太随意。我在接口层强制了三条规则所有明细查询必须带时间范围单次查询范围默认不超过 24 小时。想查一年的明细只能走聚合表。大屏数据不查明细只查预聚合表。大屏刷新频率高、并发大明细查询会瞬间打满存储节点。常用查询字段设备 ID、时间在应用层再造一层轻量索引或缓存避免每类查询都做全分片扫描。这三条规则执行下来几百用户并发查询时存储集群的压力稳定可控用户体感上也几乎没有转圈的情况。7. 成本与隐私的平衡家庭场景分布式存储的另一种解法7.1 先算一笔账云服务和私有化部署怎么选分布式存储方案听起来很高大上但落到智能家居场景用户对成本非常敏感。我做过一个简单对比方案优点缺点适用场景纯云服务免运维、弹性扩缩容长期存储成本高视频流量费贵追求省心、预算充足的商业项目纯私有化部署一次性硬件投入长跑成本低需要运维能力硬件故障要自己处理有技术团队、注重数据主权混合部署热数据本地、冷数据上云链路复杂需要做数据同步绝大多数智能家居项目混合部署是目前很多项目的落地答案实时控制和最近几天的数据留在本地分布式集群体验好且隐私有保障超过保留期的视频和明细归档到云对象存储按量付费成本可控。数据同步用简单的定时导出任务或生命周期规则就能实现不需要额外引入复杂组件。7.2 边缘节点参与存储不是所有数据都要进中心分布式存储不等于“所有数据都集中到中心集群”。智能家居场景有一个天然优势网关和中枢设备本身就有存储能力。我后来把一部分数据留在边缘涉及隐私的视频室内画面默认只存在家里网关或 NAS 的本地存储中云端只同步事件摘要和告警截帧。需要回看时App 通过安全隧道访问本地存储。关键传感器的实时状态边缘网关缓存最近 1 小时中心存储短暂不可用时App 仍能读到边缘缓存的数据中心恢复后再补齐。这套“中心 边缘”的混合架构既让整体具备分布式存储的扩展能力又保住了用户对隐私数据的主权感。这也是智能家居数据存储和互联网大数据平台一个明显不同的地方。7.3 加密与权限控制分布式不等于裸奔数据分散到多个节点后权限和加密反而更需要重视。我踩过一个险MinIO 桶权限配置成了公共读内网里任何人拿到 URL 就能直接看视频。后来的做法是传输层全链路 TLS设备到网关、网关到服务端、服务端到存储节点都启用。存储层加密对象存储启用服务端加密数据库敏感字段家庭住址、账号等用应用层加密。访问控制采用最小权限设备 token 只允许上报自己的数据用户 token 只能读自己家庭的数据管理端 token 单独签发并定期轮换。日志审计所有数据读取操作记录审计日志尤其是视频文件的访问路径。分布式存储分散的是数据不是权限。权限模型设计得越早后面要补的洞就越少。写到这里这套基于大数据分布式存储思路的智能家居数据存储方案就算完整交代清楚了。从一个 MySQL NAS 撑不住的小项目到现在 TDengine 管时序、MinIO 管文件、Kafka 削峰、Redis 加速、边缘节点兜底的整套链路回头看最深的体会是不要把分布式当成目的它只是数据规模逼到一定程度后的必然手段。做存储架构之前多花点时间在数据分类和容量估算上比盲目追求新技术有用得多。最后分享一条实操中换来的建议无论选哪种技术栈先跑一个最小规模的压测用真实设备数据灌进去跑一周然后每周导出一次容量增长曲线。只要每周曲线是发散的迟早要出问题越早发现越好处理。祝大家的智能家居项目都能稳稳跑上几年。
返回列表