【实践案例】Databricks 数据洞察在美的暖通与楼宇的应用实践
作者
美的暖通与楼宇事业部 先行研究中心智能技术部
美的暖通 IoT 数据平台建设背景
美的暖通与楼宇事业部(以下简称美的暖通)是美的集团旗下五大板块之一,产品覆盖多联机组、大型冷水机组、单元机、机房空调、扶梯、直梯、货梯以及楼宇自控软件和建筑弱电集成解决方案,远销海内外200多个国家。当前事业部设备数据上云仅停留在数据存储层面,缺乏挖掘数据价值的平台,造成大量数据荒废,并且不断消耗存储资源,增加存储费用和维护成本。另一方面,现有数据驱动应用缺乏部署平台,难以产生实际价值。因此,急需统一通用的 IoT 数据平台,以支持设备运行数据的快速分析和建模。
我们的 IoT 数据平台建设基于阿里云 Databricks 数据洞察全托管 Spark 产品,以下是整体业务架构图。在本文后面的章节,我们将就IoT数据平台建设技术选型上的一些思考,以及 Spark 技术栈尤其是 Delta Lake 场景的应用实践做一下分享。

选择 Spark & Delta Lake
在数据平台计算引擎层技术选型上,由于我们数据团队刚刚成立,前期的架构选型我们做了很多的调研,综合各个方面考虑,希望选择一个成熟且统一的平台:既能够支持数据处理、数据分析场景,也能够很好地支撑数据科学场景。加上团队成员对 Python 及 Spark 的经验丰富,所以,从一开始就将目标锁定到了 Spark 技术栈。
选择 Databricks 数据洞察 Delta Lake
通过与阿里云计算平台团队进行多方面的技术交流以及实际的概念验证,我们最终选择了阿里云 Databricks 数据洞察产品。作为 Spark 引擎的母公司,其商业版 Spark 引擎,全托管 Spark 技术栈,统一的数据工程和数据科学等,都是我们决定选择 Databricks 数据洞察的重要原因。
具体来看,Databricks 数据洞察提供的核心优势如下:
- Saas 全托管 Spark:免运维,无需关注底层资源情况,降低运维成本,聚焦分析业务
- 完整 Spark 技术栈集成:一站式集成 Spark 引擎和 Delta Lake 数据湖,100%兼容开源 Spark 社区版;Databricks 做商业支持,最快体验 Spark 最新版本特性
- 总成本降低:商业版本 Spark 及 Delta Lake 性能优势显著;同时基于计算存储分离架构,存储依托阿里云 OSS 对象存储,借助阿里云 JindoFS 缓存层加速;能够有效降低集群总体使用成本
- 高品质支持以及SLA保障:阿里云和 Databricks 提供覆盖 Spark 全栈的技术支持;提供商业化 SLA 保障与7*24小时 Databricks 专家支持服务
IoT 数据平台整体架构

整体的架构如上图所示。
我们接入的 IoT 数据分为两部分,历史存量数据和实时数据。目前,历史存量数据是通过 Spark SQL 以天为单位从不同客户关系数据库批量导入 Delta Lake 表中;实时数据通过 IoT 平台采集到云 Kafka ,经由 Spark Structured Streaming 消费后实时写入到 Delta Lake 表中。在这个过程中,我们将实时数据和历史数据都 sink 到同一张 Delta 表里,这种批流一体操作可大大简化我们的 ETL 流程(参考后面的案例部分)。数据管道下游,我们对接数据分析及数据科学工作流。
IoT 数据采集:从 Little Data 到 Big Data
作为 IoT 场景的典型应用,美的暖通最核心的数据均来自 IoT 终端设备。在整个 IoT 环境下,分布着无数个终端传感器。从小的维度看,传感器产生的数据本身属于 Small Data(或者称为 Little Data)。当把所有传感器连接成一个大的 IoT 网络,产生自不同传感器的数据经由 Gateway 与云端相连接,并最终在云端形成 Big Data 。
在我们的场景下,IoT 平台本身会对不同协议的数据进行初步解析,通过定制的硬件网络设备将解析后的半结构化 JSON 数据经由网络发送到云 Kafka。云 Kafka 扮演了整个数据管道的入口。
数据入湖:Delta Lake
IoT 场景下的数据有如下几个特点:
- 时序数据:传感器产生的数据记录中包含时间相关的信息,数据本身具有时间属性,因此不同的数据之间可能存在一定的相关性。利用 as-of-join 将不同时间序列数据 join 到一起是下游数据预测分析的基础
- 数据的实时性:传感器实时生成数据并以最低延迟的方式传输到数据管道,触发规则引擎,生成告警和事件,通知相关工作人员。
- 数据体量巨大:IoT 网络环境下遍布各地的成千上万台设备及其传感器再通过接入服务将海量的数据归集到平台
- 数据协议多样:通常在 IoT 平台接入的不同种类设备中,上传数据协议种类多样,数据编码格式不统一
IoT 数据上述特点给数据处理、数据分析及数据科学等带来了诸多挑战,庆幸的是,这些挑战借助 Spark 和 Delta Lake 都可以很好地应对。Delta Lake 提供了 ACID 事务保证,支持增量更新数据表以及流批同时写数据。借助 Spark Structed Streaming 可以实现 IoT 时序数据实时入湖。
以下是 Delta Lake 经典的三级数据表架构。具体到美的暖通 IoT 数据场景,我们针对每一层级的数据表分别做了如下定义:

- Bronze 表:存储原生数据(Raw Data),数据经由 Spark Structed Streaming 从 Kafka 消费下来后 upsert 进 Delta Lake 表,该表作为唯一的真实数据表 (Single Source of Truth)
- Silver表:该表是在对 Bronze 表的数据进行加工处理的基础上生成的中间表,在美的暖通的场景下,数据加工处理的步骤涉及到一些复杂的时序数据计算逻辑,这些逻辑都包装在了 Pandas UDF 里提供给 Spark 计算使用
- Gold 表:Silver 表的数据施加 Schema 约束并做进一步清洗后的数据汇入 Gold 表,该表提供给下游的 Ad Hoc 查询分析及数据科学使用
数据分析:Ad-Hoc 查询
我们内部在开源 Superset 基础上定制了内部版本的 SQL 查询与数据可视化平台,通过 PyHive 连接到 Databricks 数据洞察 Spark Thrift Server 服务,可以将 SQL 提交到集群上。商业版本的 thrift server 在可用性及性能方面都做了增强,Databricks 数据洞察针对 JDBC 连接安全认证提供了基于 LDAP 的用户认证实现。借助 Superset ,数据分析师及数据科学家可以快速高效的对 Delta Lake 表进行数据探索。
数据科学:Workspace
楼宇能耗预测与设备故障诊断预测是美的暖通 IoT 大数据平台建设的两个主要业务目标。在 IoT 数据管道下游,需要对接机器学习平台。现阶段为了更快速方便地支撑起数据科学场景,我们将 Databricks 数据洞察集群与阿里云数据开发平台 DDC 打通。DDC 集成了在数据科学场景下更友好的 Jupyter Notebook ,通过在 Jupyter 上使用 PySpark ,可以将作业跑到 Databricks 数据洞察集群上;同时,也可以借助 Apache Airflow 对作业进行调度。同时,考虑到机器学习模型构建、迭代训练、指标检测、部署等基本环节,我们也在探索 MLOps ,目前这部分工作还在筹备中。
典型应用场景介绍
Delta Lake 数据入湖(批流一体)
使用 UDF 函数定义流数据写入 Delta Lake 的 Merge 规则
%spark
import org.apache.spark.sql._
import io.delta.tables._ // Function to upsert `microBatchOutputDF` into Delta table using MERGE
def upsertToDelta(microBatchOutputDF: DataFrame, batchId: Long) {
// Set the dataframe to view name
microBatchOutputDF.createOrReplaceTempView("updates")
// Use the view name to apply MERGE
// NOTE: You have to use the SparkSession that has been used to define the `updates` dataframe
microBatchOutputDF.sparkSession.sql(s"""
MERGE INTO delta_{table_name} t
USING updates s
ON s.uuid = t.uuid
WHEN MATCHED THEN UPDATE SET
t.device_id = s.device_id,
t.indoor_temperature =
s.indoor_temperature,
t.ouoor_temperature = s.ouoor_temperature,
t.chiller_temperature =
s.chiller_temperature,
t.electricity = s.electricity,
t.protocal_version = s.protocal_version,
t.dt=s.dt,
t.update_time=current_timestamp()
WHEN NOT MATCHED THEN INSERT
(t.uuid,t.device_id,t.indoor_temperature,t.ouoor_temperature ,t.chiller_temperature
,t.electricity,t.protocal_version,t.dt,t.create_time,t.update_time)
values
(s.uuid,s.device_id,s.indoor_temperature,s.ouoor_temperature,s.chiller_temperature,s.electricity,s.protocal_version
,s.dt,current_timestamp(),current_timestamp())
""")
}
使用 Spark Structured Streaming 实时流写入 Delta Lake
%spark import org.apache.spark.sql.functions._
import org.apache.spark.sql.streaming.Trigger def getquery(checkpoint_dir:String,tableName:String,servers:String,topic:String ) {
var streamingInputDF =
spark.readStream
.format("kafka")
.option("kafka.bootstrap.servers", servers)
.option("subscribe", topic)
.option("startingOffsets", "latest")
.option("minPartitions", "10")
.option("failOnDataLoss", "true")
.load()
val resDF=streamingInputDF
.select(col("value").cast("string"))
.withColumn("newMessage",split(col("value"), " "))
.filter(col("newMessage").getItem(7).isNotNull)
.select(
col("newMessage").getItem(0).as("uuid"),
col("newMessage").getItem(1).as("device_id"),
col("newMessage").getItem(2).as("indoor_temperature"),
col("newMessage").getItem(3).as("ouoor_temperature"),
col("newMessage").getItem(4).as("chiller_temperature"),
col("newMessage").getItem(5).as("electricity"),
col("newMessage").getItem(6).as("protocal_version")
)
.withColumn("dt",date_format(current_date(),"yyyyMMdd"))
val query = resDF
.writeStream
.format("delta")
.option("checkpointLocation", checkpoint_dir)
.trigger(Trigger.ProcessingTime("60 seconds")) // 执行流处理时间间隔
.foreachBatch(upsertToDelta _) //引用upsertToDelta函数
.outputMode("update")
query.start()
}
数据灾备:Deep Clone
由于 Delta Lake 的数据仅接入实时数据,对于存量历史数据我们是通过 SparkSQL 一次性 Sink Delta Lake 的表中,这样我们流和批处理时只维护一张 Delta 表,所以我们只在最初对这两部分数据做一次 Merge 操作。同时为了保证数据的高安全,我们使用 Databricks Deep Clone 来做数据灾备,每天会定时更新来维护一张从表以备用。对于每日新增的数据,使用 Deep Clone 同样只会对新数据 Insert 对需要更新的数据 Update 操作,这样可以大大提高执行效率。
CREATE OR REPLACE TABLE delta.delta_{table_name}_clone
DEEP CLONE delta.delta_{table_name};
性能优化:OPTIMIZE & Z-Ordering
在流处理场景下会产生大量的小文件,大量小文件的存在会严重影响数据系统的读性能。Delta Lake 提供了 OPTIMIZE 命令,可以将小文件进行合并压缩,另外,针对 Ad-Hoc 查询场景,由于涉及对单表多个维度数据的查询,我们借助 Delta Lake 提供的 Z-Ordering 机制,可以有效提升查询的性能。从而极大提升读取表的性能。DeltaLake 本身提供了 Auto Optimize 选项,但是会牺牲少量写性能,增加数据写入 delta 表的延迟。相反,执行 OPTIMIZE 命令并不会影响写的性能,因为 Delta Lake 本身支持 MVCC,支持 OPTIMIZE 的同时并发执行写操作。因此,我们采用定期触发执行 OPTIMIZE 的方案,每小时通过 OPTIMIZE 做一次合并小文件操作,同时执行 VACCUM 来清理过期数据文件:
OPTIMIZE delta.delta_{table_name} ZORDER by device_id, indoor_temperature;
set spark.databricks.delta.retentionDurationCheck.enabled = false;
VACUUM delta.delta_{table_name} RETAIN 1 HOURS;
另外,针对 Ad-Hoc 查询场景,由于涉及对单表多个维度数据的查询,我们借助 Delta Lake 提供的 Z-Ordering 机制,可以有效提升查询的性能。
总结与展望
我们基于阿里云 Databricks 数据洞察产品提供的商业版 Spark 及 Delta Lake 技术栈快速构建了 IoT 数据处理平台,Databricks 数据洞察全托管免运维、商业版本引擎性能上的优势以及计算/存储分离的架构,为我们节省了总体成本。同时,Databricks 数据洞察产品自身提供的丰富特性,也极大提升了我们数据团队的生产力,为数据分析业务的快速开展交付奠定了基础。未来,美的暖通希望与阿里云 Databricks 数据洞察团队针对 IoT 场景输出更多行业先进解决方案。
原文链接
本文为阿里云原创内容,未经允许不得转载。
【实践案例】Databricks 数据洞察在美的暖通与楼宇的应用实践的更多相关文章
- Agora 教程丨一个典型案例,教你如何使用水晶球“数据洞察”
7 月初,声网Agora 水晶球的"数据洞察"功能正式版上线."数据洞察"可显示两种数据,一种是用量,另一种是质量. "数据洞察"的&quo ...
- 《数据可视化之美》高清PDF全彩版|百度网盘免费下载|Python数据可视化
<数据可视化之美>高清PDF全彩版|百度网盘免费下载|Python数据可视化 提取码:i0il 内容简介 <数据可视化之美>内容简介:可视化是数据描述的图形表示,旨在一目了然地 ...
- 美图App的移动端DNS优化实践:HTTPS请求耗时减小近半
本文引用了颜向群发表于高可用架构公众号上的文章<聊聊HTTPS环境DNS优化:美图App请求耗时节约近半案例>的部分内容,感谢原作者. 1.引言 移动互联网时代,APP 厂商之间的竞争非常 ...
- 《SaltStack技术入门与实践》—— 实践案例 <中小型Web架构>3 Memcached配置管理
实践案例 <中小型Web架构>3 Memcached配置管理 本章节参考<SaltStack技术入门与实践>,感谢该书作者: 刘继伟.沈灿.赵舜东 Memcached介绍 Me ...
- 实践案例:平安健康的 Dubbo3 迁移历程总结
本篇是 Apache Dubbo 的实践案例.感兴趣的朋友可以访问官网了解更多详情,或搜索关注官方微信公众号 Apache Dubbo 跟进最新动态. 1 背景 我们公司从15年开始就使⽤dubbo作 ...
- 实践案例:同程艺龙网的 Dubbo 升级经验总结
本篇为同程艺龙旅行网 Apache Dubbo 的实践案例总结.感兴趣的朋友可以访问官网了解更多详情,或搜索关注官方微信公众号 Apache Dubbo 跟进最新动态. 作者信息: 严浩:同程艺龙高级 ...
- T-SQL使用案例——结果数据前面自动补0
原文:T-SQL使用案例--结果数据前面自动补0 现象: 在开发的过程中,往往需要数字和字符串互转.在转换的过程中,可能需要把1编程00001,这样的格式.实现这种样子是有非常多的方法,本文主要提供一 ...
- DDD实践案例:引入事件驱动与中间件机制来实现后台管理功能
DDD实践案例:引入事件驱动与中间件机制来实现后台管理功能 一.引言 在当前的电子商务平台中,用户下完订单之后,然后店家会在后台看到客户下的订单,然后店家可以对客户的订单进行发货操作.此时客户会在自己 ...
- 微服务实战(四):服务发现的可行方案以及实践案例 - DockOne.io
原文:微服务实战(四):服务发现的可行方案以及实践案例 - DockOne.io 这是关于使用微服务架构创建应用系列的第四篇文章.第一篇介绍了微服务架构的模式,讨论了使用微服务架构的优缺点.第二和第三 ...
- - 反编译 AndroidKiller 逆向 实践案例 MD
目录 目录 反编译 AndroidKiller 逆向 实践案例 MD AndroidKiller 简介 插件升级 基本使用 实践案例 修改清单文件 打印 debug 级别的日志 方式一:直接代理 Lo ...
随机推荐
- Libcurl & Log4cplus 移植和使用 以及 Jsoncpp 简单使用
PS:要转载请注明出处,本人版权所有. PS: 这个只是基于<我自己>的理解, 如果和你的原则及想法相冲突,请谅解,勿喷. 前置说明 本文作为本人csdn blog的主站的备份.(Bl ...
- django(cookie与session、中间件、auth模块)
一 cookie与session 1 发展史及简介 """ 发展史 1.网站都没有保存用户功能的需求,所有用户访问返回的结果都是一样的 eg:新闻.博客.文章 2.出现了 ...
- django(图书管理系统)
一.表的设计 from django.db import models # Create your models here. class Book(models.Model): title = mod ...
- 记录--手把手带你开发一个uni-app日历插件(并发布)
这里给大家分享我在网上总结出来的一些知识,希望对大家有所帮助 相信我们在开发各类小程序或者H5,甚至APP时,会把uni-app作为一个技术选型,其优点在于一键打包多端运行,较为强大的跨平台的性能.但 ...
- pandas 自动化处理Excel数据
需求: 如下一份这样的Excel数据 现在需要把学生的学号.姓名分离出来到单独的一列 ,将 测验.讨论.成绩三列转换成数值,并把讨论这列的"-"转换成 0 显示 最后把处理好的内 ...
- [SQL]SQL注入与SQL执行过程(基于JDBC)
[版权声明]未经博主同意,谢绝转载!(请尊重原创,博主保留追究权) https://www.cnblogs.com/cnb-yuchen/p/17955065 出自[进步*于辰的博客] 参考笔记一,P ...
- 从静态到动态化,Python数据可视化中的Matplotlib和Seaborn
本文分享自华为云社区<Python数据可视化大揭秘:Matplotlib和Seaborn高效应用指南>,作者: 柠檬味拥抱. 安装Matplotlib和Seaborn 首先,确保你已经安装 ...
- C# 按指定宽高缩放图片
/// <summary> /// 按指定宽高缩放图片 /// </summary> /// <param name="image">原图片&l ...
- KingbaseES V8R6 索引膨胀
索引膨胀 对于索引,随着业务不断的增删改,会造成膨胀,尤其Btree索引,也会涉及索引分裂.合并等,导致索引访问效率降低.维护成本增加.另外,索引页的复用与HEAP PAGE不一样,因为索引的内容是有 ...
- archlinux virtualbox 启用usb支持
参照 https://linux.cn/article-15287-1.html 1.安装virtualbox扩展包 (1)从archlinuxcn社区库安装 sudo pacman -S virtu ...