如果您曾经构建过分析仪表板,很可能接触过传统的“批量加载到RDS”模式——通过批处理将数据加载到RDS,然后从该操作数据存储(如AWS RDS或其他数据库)中读取数据。我们确实采用了这种方式,并且在一段时间内它运行良好。
我们的应用程序从Snowflake或Delta Lake等数据湖中提取数据,在AWS Glue中进行转换,然后加载到Amazon RDS。RDS数据库为Lambda API提供支持,这些API为仪表板前端应用程序提供数据。
但随着我们平台的扩展,这种模式开始显露出其局限性:
- 数据延迟:批量更新意味着仪表板总是比源数据落后几个小时,有时甚至是一整天
- 操作开销:ETL管道中断、模式变更级联、恢复过程消耗工程时间
- 成本上升:即使没有人查询数据,我们也要为RDS集群和ETL计算付费
- 数据漂移:分析师在Snowflake中看到一个版本的数据,而用户通过RDS API看到的是另一个版本
最终,我们清楚地认识到基于批处理的设计不可持续。我们需要更快、更精简、更接近实时的解决方案。
我们的传统设置:批处理驱动设计
这是我们旧的数据流:
|
|
每天晚上,AWS Glue作业从Snowflake和Delta Lake填充RDS表。然后API将这些表提供给仪表板和分析应用程序。
这种方式确实有效——但到了一定程度后,批处理作业延长到六个小时以上,RDS成本飙升,每个模式调整都需要多个协调变更。整个系统变得僵化且维护成本高昂。
转变:转向查询源架构
目标很简单:去掉中间层。我们希望消除持久化的RDS层,停止通过夜间ETL周期推送数据。相反,API通过Databricks SQL直接查询治理的数据源。
新的数据流如下:
|
|
这一单一变更移除了多个移动部件,显著简化了我们的服务层。
关键构建模块
- 前端:用于数据健康监测的交互式仪表板
- API层:基于AWS Lambda构建的无状态REST API,通过JDBC直接连接到Databricks SQL
- 查询引擎:由Unity Catalog管理的Databricks SQL端点,处理访问和安全性
- 数据源:经过整理的Delta表和来自Snowflake及数据湖的联合数据
实施细节
- Lambda使用基于令牌的身份验证安全建立JDBC会话
- API将传入请求转换为参数化SQL查询,确保安全过滤和防止注入
- Databricks SQL实时针对Delta和联合表执行这些查询
- 结果直接流式传输回客户端——无需暂存,无延迟
结果:更精简、更快、更便宜
迁移完成后,效果立竿见影。我们的仪表板开始显示近乎实时的数据,曾经通宵运行的ETL管道消失了。
以下是我们的数据流演变快照——从传统的批处理驱动RDS设置到由Databricks SQL支持的实时查询架构:
前后对比:数据服务架构的演变
通过移除RDS层和批处理ETL作业,我们:
- 将基础设施成本降低了近70%
- 消除了每周4-6小时的维护和监控工作
- 移除了1-2小时的夜间批处理窗口,将数据新鲜度提高到近实时
- 将技术栈简化为仅两个组件:AWS Lambda和Databricks SQL
现在的设置完全是无服务器的——按需扩展,无需固定基础设施。
经验教训与优化技巧
查询源模型不是即插即用的;需要仔细优化才能在规模上表现良好。以下是我们在此过程中学到的一些经验:
挑战
- 对大型未优化数据集的查询可能比预聚合的RDS表慢
- API驱动请求的高并发可能导致排队
- Lambda冷启动增加了JDBC的连接开销
有效的优化
- 结果缓存:Databricks SQL缓存重复查询,在毫秒内返回结果
- 无服务器端点:自动扩展以处理不同的查询负载
- 分区和Z排序:优化Delta表以最小化数据扫描
- API防护:分页、投影下推和LIMIT子句确保高效查询
- 预聚合表:对于亚秒级延迟仪表板,我们在数据湖中直接维护轻量级汇总表
总结
转向查询源模式改变了我们提供分析数据的方式。最初的成本优化练习变成了一种思维转变——让数据湖本身成为服务层。
像Databricks SQL这样的现代查询引擎快速、安全且可扩展,足以支持实时分析API——如果配合适当的优化。对于正在努力应对过时仪表板、不断上涨的数据库账单或脆弱的ETL管道的团队来说,这种架构提供了一条通往简单性、速度和可持续性的清晰路径。