Databricks中以時間為設(shè)計核心的實踐思考
不久前,我分享了一篇叫做“以时间为本的设计”的思考,在这篇文章中,我讨论了将 时间(time)作为核心元素如何帮助塑造更优质、更值得信赖的数据解决方案架构。
那篇文章源于我在实际项目中积累的经验和教训;一些无论在哪个平台或使用什么技术都会常常遇到的知识和教训。
从那以后,通过这几年与Databricks的合作,我得以用更具体的方式来重新审视那些想法。
我见过Databricks的设计方式,特别地,其Delta Lake及其原生的时间处理,为构建能够尊重数据时间特性的系统提供了实用支持,而无需复杂的补救措施。
这次,我想直接延续之前的思考;特别想探讨一下Databricks是如何将这些原则变为日常操作的。
这并不是一个功能介绍或平台宣传。这只是关于设计选择、取舍和在真实数据工作中如何合理使用时间的讨论的实际扩展。
无论是你阅读了这篇原文章,还是你只是关心构建更加周到的数据解决方案,希望你能在这里找到一些共鸣之处。
我们在Databricks设计时考虑了时间因素
1. Databricks 如何以时间考虑构建在我之前的反思中,我指出了时间不仅仅是一个附加在数据上的属性;它常常赋予数据本身的意义。
然而,设计这样的系统设计是有挑战性的,特别是当底层平台把这些特性(如历史记录、版本控制或审计)当作可选功能时。
在使用 Databricks,尤其是 Delta Lake 的过程中,我发现了一种不同的体验方式。时间不再需要通过临时表来模拟,也不需要通过复杂的流程手动管理。它已经成为平台基础的一部分。
每个 Delta 表 都有一个 事务日志:一个结构化且不可变的记录,记录了所有操作,包括所有的插入、更新和删除操作,每个操作都附带了时间戳和元数据。
这种方法确保数据集不仅反映最新的状态,还记录了其演变的可追踪历史。
因为这个设计,Databricks 让它变得实用。
- 查询特定时间点的数据状态(时间旅行)。
- 利用内置透明度审计和追踪更改。
- 无需外部框架即可访问结构化的变更数据馈送。
让我印象最深的是这些功能是如何自然而然地集成进来的。
在许多平台中,历史是围绕系统建立的。在 Databricks 中,历史从一开始就内置在系统中。
无论是批处理还是流处理,相同的 Delta 架构都能确保时间一致性。
治理(稍后会进一步讨论)不仅限于最新的快照,还涵盖了过去的版本,并且功能如VACUUM 可以在不影响可追溯性的情况下,实现对历史数据的有效管理。
当然,拥有强大的平台基础并不意味着谨慎的设计就不那么重要了。实际上,这把责任转移了:从应对技术限制到做出良好的架构决策,关于如何有效表示和处理时间。
在接下来的部分中,我将介绍一些实用场景,Databricks 帮助将这些具有时间意识的设计原则应用到实际工作中。
Databricks 平台中的每个 Delta 表都会维护一个事务日志记录。
2. 由 Databricks 支持的实用模式在 Databricks 平台中,几个实用模式自然而然地出现;不是因为平台强制它们(好吧……实际上,有时它确实会引导你去使用这些模式);而是因为当你选择使用它们时,平台会使这些模式更容易被采纳。
在考虑时间因素的设计时,会出现两个重要的维度:数据本身是如何随时间变化的,以及数据结构(即数据库模式)是如何随时间变化的。
两者都至关重要,这样我们的系统才能保持可信赖、灵活和有弹性。
Databricks(结合Delta Lake)都提供了强大的内置支持。
2.1. 数据版本管理和时间维度访问在时间感知设计中,最常被问到的问题之一是:
“我怎么知道特定时刻的数据是什么样的?”
在许多平台上,回答这个问题通常需要构建复杂的版本记录表、维护手动快照记录或添加审计层,这些都会带来显著的额外负担。
我并不是直接比较这些平台,但如果你熟悉像Azure Synapse Analytics、Google BigQuery或Snowflake这样的平台,你可能会发现其中的一些挑战。
Synapse 中不提供内置的数据版本支持,用户通常需要自己搭建定制化的解决方案,通过快照表或审计列来记录变更。
BigQuery 提供了一些有限的基于时间的查询能力,但要确保可靠的长期版本记录,仍然主要依赖于手动快照和细致的表管理。
即使 Snowflake 提供了时间旅行特性,但其功能仅限于可配置的保留期(通常不超过 90 天);要维护更长的历史记录,仍需克隆或归档。
相比之下,Databricks 提供内置的自动持久的数据版本管理功能。
时间旅行功能(https://www.databricks.com/blog/2019/02/04/introducing-delta-time-travel-for-large-scale-data-lakes.html)不是围绕平台构建的功能;它是一个内在的能力。你可以查询表在特定时间戳或版本号的确切状态,如有必要,可以恢复到以前的状态,或者比较历史版本以了解数据的演变。
这使得实际场景变得更加简单和安全,比如审计调查、回顾过去的决策或回滚管道操作等。
而且,从另一个角度来看,也许更重要的是,它改变了团队应对变化的态度和方式!团队不再构建僵化的系统来避免所有可能的错误发生,而是可以设计能够 接受调整 并优雅地处理迟到的数据和信息的系统;因为所有的历史记录都不会丢失!
数据版本
2.2. 架构版本化数据并非是唯一会随时间变化的事物。随着业务的发展变化,会添加新列,调整数据类型,并对模型进行调整和完善。
管理这些模式变化而不影响数据流管道的正常运行,与处理数据变化一样同等重要。
Delta Lake 内建支持模式演进和强制。
这种平衡意味着模式漂移不会破坏数据集,同时仍然给你灵活适应业务需求变化的能力,而避免了长时间停机和手动迁移的麻烦。
目前为止,重点一直是将时间作为回顾过去的方式:版本、历史和演变的过程。
但在数据系统中,时间还有另一个角色,它关注的是现在而不是过去发生的,处理的是正在发生的事情。
在这种视角下,时间不再是记录中的被动参考。它成为了一种积极的力量,影响着数据在系统中的流动方式和处理时机。
Databricks 通过其统一的批处理和流式处理方法,让时间的流动特性在日常设计中更清晰可见,也更便于管理。
3.1 Databricks中的事件时间与处理时间概念在构建实时或接近实时的数据管道时,一个重要的发现是,时间可以从多个角度来理解。
_事件时间_记录了某件事实际发生的时间。
处理时间 指的是系统观察到或对其采取行动的时间点。
一个注释:
在我刚开始接触数据系统时,我有点搞不清同步和异步处理之间的区别。同步和异步这两个术语已经是标准的计算机术语。
这实际上是一个很好地进行区分的地方。
在同步系统中,操作通常会立即处理,因此事件时间和处理时间几乎一致。
在异步系统里,事件可能会被延迟、排队或重新排序,之后再进行处理,也就是说,事件时间和处理时间可能会脱节得很厉害,这样更符合原文中的“drift apart significantly”。
流处理架构,因为这些架构本质上是异步的,包括当今大多数实时系统,这也是为什么事件时间与处理时间之间的差异如此重要。
在批量处理过程中,这种差异通常不易被察觉。数据先被收集,然后在稍后的某个时间批量处理,这使得事件发生的时间与数据处理时间之间的间隔不那么明显。
但在流处理中,尤其是在网络延迟、重试和并行处理常见的分布式系统中,这变得非常重要,是设计中的关键考虑。
Databricks 结构化流使明确地建模这种区分变得实际可行。
你可以搭建处理数据的流水线,根据事件的实际发生时间来处理,而不仅仅根据事件到达的时间来处理,这样的方式。
等会儿……你可能很快读完了上面的内容,而没有注意到这其实有多重要和酷……
我要告诉你:在 Databricks 中,你可以接收到实际在 10:01 产生的传感器读数,但直到 10:07 才收到,并且仍能正确地将其视为 10:00 至 10:05 时间窗口的一部分;只要你把系统设置为可以容忍一些延迟!
系统不仅在接收到数据时才做出反应,还会考虑事件实际发生的时间,这一区别对于构建准确和值得信赖的流程非常重要。
你怀疑这个?嗯,我以前也这么想过,不过从技术上讲,确实是这样的。通过使用水印,你可以设定系统在关闭一个计算窗口前能接受的最大延迟。
这直接影响了系统如何回答架构性问题,比如:这个系统多晚收到的信息就算太晚了?以及五分钟前收到的数据是否仍然有效?
Databricks 中的管道时效性和调度并不是每个数据系统都运行在连续流模式下,许多系统仍然依赖于计划管道;每小时摄入,夜间转换,每天刷新。
即使在这里,时间依然很重要。它决定了数据是否新鲜以及下游用户能多快做出反应。
Databricks 工作流工具 提供了编排工具来精确地调度和监控数据管道。作业可以在类似 cron 的定时任务上运行,也可以由数据可用性触发作业,或对事件作出响应。
任务之间的依赖关系可以设定,同时可以设定重试来处理暂时性故障。
我确实同意你的观点,你可能会说,在很多地方,调度任务、设置重试和管理任务依赖确实是很常见的。你说得对极了!
但 Databricks 的与众不同之处在于,编排 并未与计算和数据分离。工作流程天生了解笔记本、Delta 表和 Delta 活管道,使任务可以直接触发它们,而无需外部连接器或额外的编排层。
在许多其他平台上,编排引擎(编排引擎在这里指的是任务调度和协调的工具)与实际计算引擎是分离的,任务被视为黑盒,通过API或外部脚本进行连接。黑盒(指内部工作方式不可见的组件)。
在 Databricks 中,工作流内置于平台中,这意味着任务可以直接执行数据转换操作、训练或应用机器学习模型或刷新 SQL 仪表板内容,而无需在不同系统间搭建桥梁。
Databricks中的管道时效性和调度
每个任务甚至可以优化自身的计算资源,必要时可利用特定的集群;这种灵活性在当编排与计算分别位于不同系统中时,并不总是很容易实现。
使用Delta Live Tables (DLT),这些概念得以进一步扩展。DLT带来了管理管道能力,可以自动监控数据的新鲜度并追踪服务水平协议(SLA)的违反情况,并在适当的时候重试失败的处理过程。它将管道健康作为核心关注点,不仅关注数据是否按时加载,还关注加载的准确性。
在这里,我无法深入探讨DLT(DLT本身确实值得单独讨论……甚至可能引发一些辩论 :) ),但关键在于时间如何自然地融入并受到尊重在整个Databricks平台中的各个部分,不论是流式处理、批处理还是管理管道。
4. 机器学习中的时间:Databricks 和 MLflow 如何让其变得实用其中一点是,我非常欣赏与Databricks合作时,有一个统一的一体化平台;数据工程、数据科学和机器学习这些不再分散在不同的工具中,而是整合到了同一个环境里,这让我觉得非常方便。
这种一致性在微妙的概念比如时间开始影响机器学习系统的设计时更为重要,这些概念往往在不知不觉中发挥作用。
除了时间序列模型外,时间在其他机器学习系统中很少明确体现。然而,它会影响模型漂移现象、特征过时以及训练和部署环境之间的不一致,常常悄然侵蚀用户对预测的信任。
Databricks 通过与 MLflow 的集成,使得这些时间信号能够有意而非偶然地展现出来。
我在与机器学习系统合作时学到的一个较为安静的教训是,模型很少突然彻底失败,更常见的是,它们会悄无声息地逐渐偏离正确轨道。
在早期阶段中,我们擅长捕捉明显的错误:语法错误、中断的流水线、无法收敛的指标。
但在实际生产中,更危险的故障是无声的。模型仍然在做出预测。管道仍然在运行。仪表盘仍然保持绿色。然而,决策的质量却在悄悄下滑!
变的是什么?时间。
模型被训练来理解特定时刻的模式。但这个预测的世界并不是静止不动的。企业不断发展。营销活动会推出。用户行为也会随之变化。
而且如果模型的“知识”无法跟上世界前进的步伐,那么,脱节就自然而然地发生了。
通过MLflow及其模型注册表,时间就成为模型故事中的一部分:
- 每个模型版本都包含了它被训练、验证、部署或归档的时间线。
- 训练数据集可以与模型一起记录,捕捉模型曾经认识的世界的实时快照。
- 推断端点可以记录实时特征和预测,从而在业务结果中显示出漂移迹象之前就检测到漂移。
虽然 MLflow 单独提供了这些构建块,但我认为这些都是一个更广泛能力的一部分:Databricks Lakehouse Monitoring(Databricks 湖屋监控)。
湖仓监控将这些信号整合为整个系统中的一个动态视图。
- 数据质量监控:监控输入模型数据的新鲜度、完整性和一致性。
- 模型性能:跟踪预测准确性、漂移和随时间出现的异常。
- 特征漂移检测:观察输入数据分布的变化,即使标签还未生成也应观察。
与其自己搭建分散的监控系统,Databricks Lakehouse Monitoring 将数据、特征和模型作为一个统一的系统来监控。
5. 时间治理中的时间管理:Databricks 如何处理时间治理提到Databricks中的治理时,重要的是要认识到它主要是关于Unity Catalog;这反映了治理方式的变化。
Unity Catalog 不仅仅代表集中式元数据管理。它体现了一种哲学,即信任、数据血统、访问控制和政策执行都与数据的整个生命周期紧密相连,而不是作为独立的或手动的任务来处理。
人们可能认为治理是静态的:规则、权限和权利。但当你开始在实际系统中工作时,你很快就会发现治理其实并不是一成不变的。
谁曾经有过访问权限?什么时候?他们被允许看到哪个版本的表格?什么时候记录变得敏感,或者需要被遗忘?
时间再次流逝于一切之下。
我特别欣赏的是,Databricks在与我们合作时,不仅认识到这种现实,而且直接将其融入平台,而不是将其作为后期的补丁添加。
5.1.: 版本管理作为核心特性,而不是临时修复使用 Delta Lake,每个表的变化都会被自动记录版本,附有完整的事务日志和时间戳。Unity Catalog 则利用 数据血缘图 进一步扩展了这一点,这些图可以追踪数据在平台上的移动和转换。
您可以根据截至特定时间点重建数据集,追踪数据变化;这对于审计、调查和再现结果来说非常重要。
5.2. 数据保留及生命周期管理Databricks 通过 [Delta Lake 的历史保留](https://docs.databricks.com/gcp/en/delta/history#:~:text=following%20table%20properties%3A-,delta.,默认间隔为 30 天。) 设置自动化数据保留,并集成了云存储的生命周期管理策略。
这使得组织能够实施保留规则,删除过期记录,并归档老化数据集,而无需手动处理。
5.3. 时间感知型访问控制Unity Catalog 提供基于属性的细粒度访问权限控制(ABAC)功能,可以根据用户属性、资源元数据和时间条件灵活调整。ABAC 是基于属性的访问控制的简称。
审计日志为所有访问事件加上时间戳,这不仅可以让您检查当前权限,还可以在任何时间点验证过去的访问记录。
6. 最后的感想在这段旅程中,我们讨论了Databricks如何以时间为轴心;涵盖数据存储、数据管道、机器学习和治理等领域。
回想起来,我现在觉得这一点更清楚了:
- 时间不仅仅是我们系统中的一个技术模块。它是一种默默的力量,定义了它们的真相,揭示了它们的脆弱性,并塑造了它们的战略方向。
- 没有时间,就无法信任历史查询。
- 没有时间,就无法优雅地演进模式或管道结构。
- 没有时间,就无法检测机器学习中的漂移或实现真正的治理。
- 我们设计的架构要么尊重这一现实,要么与之斗争。
现在,我确实明白,设计Databricks之初,设计师和开发人员可能并没有特意考虑到。
“咱们干脆设计一个在每一层都珍惜时间的平台吧。”
也许这更实际,没那么哲学。
不过,通过与Databricks在它架构的不同部分的合作,我不能不注意到一个一致的模式。
时间在许多层面上被默默考虑和尊重,这种做法深刻地影响了系统的长期表现。
这样的反思可能提供了一个不同于人们通常看待平台的新视角。
与其只关注速度、功能或集成,我想探索那种感觉:构建的系统能够随着时间的推移存在;以及 Databricks 是如何有意或无意地使这一过程更自然的。
谢谢你陪我走过这次反思。
共同學(xué)習(xí),寫下你的評論
評論加載中...
作者其他優(yōu)質(zhì)文章