你当前正在访问 Microsoft Azure Global Edition 技术文档网站。 如果需要访问由世纪互联运营的 Microsoft Azure 中国技术文档网站,请访问 https://docs.azure.cn

数据域

去中心化和域的责任分配是数据网格的核心基础。 如果你真正了解此业务领域,则具备了管理相关数据并确保其准确度的能力。 这就是面向域的数据所有权原则。

为帮助实现面向域的数据所有权,首先需要对数据体系结构进行分解。 数据网格创始人 Zhamak Dehghani 将域驱动设计 (DDD) 方法推广到了软件开发中,将其作为一种有用的方法来帮助识别数据域。

使用 DDD 进行数据管理的难度在于 DDD 的原始用例是在软件开发环境中为复杂系统建模。 它最初不是为了对企业数据建模而创建的,对于数据管理从业者而言,它的方法可能是抽象和技术性的。 此外他们还经常缺乏对 DDD 的理解。 从业者发现它的概念表示法很难掌握,或者试图将软件体系结构或面向对象的编程中的示例投影到其数据环境中。 本文提供务实的指导和清晰的词汇解释,让你能够理解和使用 DDD。

域驱动的设计

Eric Evans 引入的域驱动设计是一种支持软件开发的方法,用于帮助描述大型组织的复杂系统。 DDD 非常流行,因为它的许多高级实践影响了新式软件和应用程序开发方法,例如微服务。

DDD 区分边界上下文、域和子域。 域是要解决的问题空间。 它们是将知识、行为、法律和活动组合在一起的领域。 你会在域中看到语义耦合,即组件或服务之间的行为依赖关系。 域的另一个方面是通信。 团队成员必须使用整个团队共享的语言,这样每个人都可以高效地工作。 这种共享语言称为通用语言或域语言

域分解为子域以更好地处理复杂性。 一个常见示例是将域分解为子域,每个域对应于一个特定的业务问题,如 AI/ML 操作数据网格中所示。

并非所有子域都是相同的。 例如,可将域分类为核心域、通用域或支持域。 核心子域是最重要的。 它们是使组织保持独特优势的秘方调和剂。 通用子域是非特异性的,通常很容易用现成的产品来解决。 支持子域不能带来竞争优势,但对于保持组织运作是必要的,并且通常并不复杂。

边界上下文是逻辑(上下文)边界。 他们专注于解决方案空间:系统和应用程序的设计。 此领域专注于使解决方案空间发挥作用。 在 DDD 中,这可能包括代码、数据库设计等。 在域和边界上下文之间可以存在一致性,但没有将两者绑定在一起的硬性规则。 边界上下文本质上是技术性的,可以跨越多个域和子域。

域建模建议

如果你采用数据网格作为数据民主化概念,并实施面向域的数据所有权原则以提高灵活性,那么应如何将其付诸实践? 从企业数据建模转换为域驱动设计建模后会发生什么情况? 可以从 DDD 中吸取哪些数据管理经验?

对问题空间进行功能性业务分解

在允许团队端到端处理数据之前,请查看范围并了解要解决的问题空间。 在深入了解技术实现细节之前,首先完成此练习非常重要。 在这些问题空间之间设置逻辑边界时,职责会变得更加清晰并且可以更好地进行管理。

在对问题空间进行分组时,请查看业务体系结构。 业务体系结构中存在业务功能:企业拥有或交换的以实现特定目的或结果的能力或功能。 这种抽象将数据、流程、组织和技术打包到特定的上下文中,与组织的战略业务目的和目标保持一致。 业务功能映射显示了哪些职能领域似乎是完成使命和愿景所必需的。

可在以下模型中查看虚构公司 Tailwind Traders 的功能分解。

显示业务功能分解的关系图。

Tailwind Traders 需要掌握业务功能映射中列出的所有功能领域才能成功。 例如,Tailwind Traders 必须能够作为联机或脱机票务管理系统的一部分销售机票,或者作为飞行员管理计划的一部分,让飞行员可以驾驶飞机。 公司可将一些活动外包,同时将其他活动作为其业务的核心。

在实践中你将注意到,大多数人员都是围绕业务功能进行组织。 从事相同业务功能的人们共享相同的词汇。 应用程序和流程也是如此,它们通常基于它们所支持的活动的凝聚力协调一致地紧密关联。

业务功能映射是一个很好的起点,但故事并没有到此结束。

将业务功能映射到应用程序和数据

为了更好地管理企业体系结构,请调整业务功能、边界上下文和应用程序。 在采取这些措施时遵循某些基本规则非常重要。

业务功能必须停留在业务层面并保持抽象。 它们代表了组织的活动并以问题空间为目标。 实现业务功能时,将创建特定上下文的实现(功能实例)。 多个应用程序和组件在解决方案空间的此类边界内协同工作,以提供特定的业务价值。

与特定业务功能一致的应用程序和组件与与其他业务功能一致的应用程序保持分离,因为它们解决不同的业务问题。 边界上下文源自并专门映射到业务功能。 它们代表业务功能实现的边界,其行为类似于域。

如果业务功能发生变化,边界上下文也会变化。 最好是预想到域和相应的边界上下文之间完全保持一致,但是如稍后部分中所述的那样,现实有时与理想不同。

如果将功能映射投影到 Tailwind Traders,则边界上下文边界和域实现可能类似于下图。

显示边界上下文的关系图。

在此图中,客户管理建立在主题专业知识之上,因此可以最清楚地知道哪些数据将提供给其他域。 客户管理的内部体系结构是解耦的,因此这些边界中的所有应用程序组件都可以使用特定于应用程序的接口和数据模型直接通信。

数据产品和明确的互操作性标准用于正式化将数据分发到其他域的过程。 在此方法中,所有数据产品也与域保持一致并继承通用语言,这是一种由同一域的利益干系人和设计者议定的、构造的正式化语言,可满足该域的需求。

来自多个功能实现的额外域

在使用业务功能映射时,必须确认某些业务功能可以多次实例化,这一点非常重要。

例如,Tailwind Traders 可能有多个“行李处理和失物招领”的本地化实现。 假设他们的一条业务线仅在亚洲运营。 在此背景下,“行李处理和失物招领”是亚洲相关航班具备的功能。 不同的业务线可能以欧洲市场为目标,在这种背景下,使用了另一项“行李处理和失物招领”功能。 这种多实例方案可能导致使用不同技术服务的多个本地化实现和分散的团队来运营这些服务。

业务功能和功能实例(实现)之间存在一对多关系。 因此,最终会出现额外的(子)域。

查找共享功能并监视共享数据

共享业务功能的处理方式非常重要。 通常以服务模型的形式集中实现共享功能,并将其提供给不同的业务线。 “客户管理”就是这种功能的一个示例。 在 Tailwind Traders 示例中,亚洲和欧洲的业务线对其客户使用相同的管理。

但是,如何将域数据所有权投影到共享功能? 多个业务代表可能对同一共享管理中的客户负责。

有一个应用程序域和一个数据域。 从数据产品的角度看,域和边界上下文并不完全一致。 相反,你可能会争辩说,从业务功能的角度看,仍然存在单一的数据问题。

对于复杂的供应商包、SaaS 解决方案和传统系统等共享功能,请在域数据所有权方法上保持一致。 可以通过数据产品分离数据所有权,这可能需要对应用程序做出改进。 在 Tailwind Traders“客户管理”示例中,来自应用程序域的不同管道可能会生成多个数据产品:一个数据产品用于所有亚洲相关客户,一个数据产品用于所有欧洲相关客户。 在这种情况下,多个数据域源自同一个应用程序域。

你还可以要求应用程序域创建一个封装元数据的单一数据产品,以区分其内部的数据所有权。 例如,可为所有权保留一个列名,并将每一行映射到一个特定的数据域。

标识提供多种业务功能的单体结构

此外,需要注意迎合多种业务功能的应用程序,这在大型和传统企业中很常见。 在示例方案中,Tailwind Traders 使用一个复杂的软件包来简化“成本管理”及“资产和融资”。 这些共享应用程序是提供尽可能多的功能的单体结构,因此它们变得庞大而复杂。 在这种情况下,应用程序域应该更大。 同样的事情也适用于共享所有权,其中的多个数据域驻留在一个应用程序域中。

源对齐、重新传送和使用者对齐域的设计模式

映射域时,可以根据数据的创建、消耗或重新传送来选择模式。 对于体系结构,可以根据域的特定特征设计支持域的模板。

与源系统一致的域

显示源系统对齐域的关系图。

与源系统一致的域与数据来源系统保持一致。 这些系统通常是事务性或运营性的。

你的目标是直接从这些黄金源系统中捕获数据。 从提供方域读取优化数据产品以使用密集型数据。 使用标准化的数据转换和共享服务来简化这些域。

这些服务包括预配置的容器结构,能使面向源的域团队更轻松地发布数据。 这是阻力、干扰和成本最小的途径。

面向使用者的域

显示使用者对齐域的关系图。

与使用者一致的域与与源一致的域相反。 它们与需要其他域中的数据的特定最终用户用例保持一致。 与客户一致的域使用和转换数据以适合组织的用例。

考虑为数据转换和使用提供共享数据服务,以满足这些使用需求。 例如,可以提供与领域无关的数据基础结构功能,用于处理数据管道、存储基础结构、流式处理服务、分析处理等。

重新交付域

显示重新传递域的关系图。

数据可重用性是一个不同的且更困难的方案。 例如,如果下游使用者对来自不同域的数据组合感兴趣,你可以创建聚合数据的数据产品,或组合多个域所需的高级数据。 这可以避免重复性的工作。

不要在数据产品和分析用例之间建立强依赖关系。 应该争取灵活性和松散耦合。 以下模型演示如何实现灵活性。 域拥有数据产品和分析用例的所有权,并为数据产品创建和数据使用设计了单独的流程。

定义重叠域模式

跨域共享数据或业务逻辑时,域建模通常会变得复杂。 在大型组织中,域通常依赖于其他域的数据。 让通用域以一种允许其他子域标准化并从中受益的方式提供集成逻辑可能有帮助。 使子域之间的共享模型保持较小规模并始终与通用语言保持一致。

为了满足重叠数据要求,可以使用与域驱动设计不同的模式。 下面是可以选择的模式的简短摘要:

显示重叠域的 DDD 模式的关系图。

  • 如果你偏向于相关的重复成本而不是可重用性,可以使用分离方式模式。 但这样会为了获得更高的灵活性和敏捷性而牺牲了可重用性。
  • 如果一个域很强大并且愿意拥有下游使用者的数据和需求,则可以使用客户-供应商模式。 缺点包括冲突风险和迫使下游团队协商交付件和计划优先级。
  • 如果集成逻辑以非计划方式在新建的域中进行协调,可以使用合作模式。 所有团队相互协作并尊重彼此的需求。 由于没有人可以随意更改共享逻辑,每个相关人员需要做出慎重承诺。
  • 遵从者模式可用于使所有域符合所有要求。 当集成工作很复杂、其他各方无法控制或使用供应商包时,请使用此模式。

在所有情况下,域都应遵守互操作性标准。 为其他域生成新数据的合作域必须像任何其他域一样公开其数据产品,包括取得所有权。

域职责

数据网格通过在域团队之间分配数据所有权来分散数据所有权。 对于许多组织而言,这意味着从围绕治理的集中式模型转变为联合模型。 将为域团队分配如下所述的任务:

  • 取得数据管道(例如引入、清理和转换数据)的所有权,以尽量满足客户的数据需求
  • 改善数据质量,包括遵守 SLA 和数据使用者规定的质量措施
  • 封装元数据或使用保留的列名进行精细粒度的行级和列级筛选
  • 遵循元数据管理标准,包括:
    • 应用程序和源系统架构注册
    • 用于改善可发现性的元数据
    • 版本控制信息
    • 数据属性与业务术语的链接
    • 元数据信息的完整性,以便在域之间实现更好的集成
  • 遵守数据互操作性标准,包括协议、数据格式和数据类型
  • 通过将源系统和集成服务链接到扫描程序或者通过手动提供世系来提供世系
  • 坚持执行数据共享任务,包括 IAM 访问评审和数据协定创建

解耦粒度级

知道如何识别和简化数据域后,接下来可以了解如何设计正确的域粒度级和解耦规则。 分解体系结构时,有两个重要的维度在起作用。

功能域的粒度和边界上下文设置是一个维度。 域遵循特定的工作方式,确保数据可用于所有使用共享服务、取得所有权、遵守元数据标准等的域。

尽可能为数据分布设置精细粒度的边界。 数据驱动的设计无非就是使数据可密集重用。 如果边界过于松散,你将被迫在许多应用程序之间进行没有意义的耦合,并失去数据可重用性。 每当数据跨越业务功能的边界时,都请尽量解耦。 在域中,允许在域的内部体系结构中进行紧密耦合。 但是,当跨越业务功能的边界时,域必须保持解耦并分发读取优化的数据产品,以便与其他域共享。

技术域和基础结构的利用粒度是另一个重要维度。 使用数据登陆区域可以灵活地为创建数据产品的数据应用程序提供服务。 如何创建这种具有共享基础结构和底层服务的登陆区域? 功能域在逻辑上组合在一起,是共享平台基础结构的良好候选项。 下面是创建这些登陆区域时需要考虑的一些因素:

  • 处理和共享数据时的凝聚力和效率是使功能域与数据登陆区域保持一致的强大驱动力。 这与数据引力有关,即在域之间持续共享大型数据产品的趋势。
  • 区域边界可能导致实现额外的数据登陆区域。
  • 所有权、安全性或法律边界可能强制实施域隔离。 例如,某些数据可能对任何其他域都不可见。
  • 灵活性和变化步调是重要的驱动力。 有些域的创新速度很快,而有些域则非常重视稳定性。
  • 功能边界可能导致团队各司其职。 一个示例是面向源和面向使用者的边界。 有一半的域团队可能注重某些服务而不是其他服务。
  • 如果你想销售或分离功能,应该避免与其他域中的共享服务紧密集成。
  • 团队规模、技能和成熟度都是重要因素。 训练有素的成熟团队通常更喜欢操作自己的服务和基础结构,而不成熟的团队不太可能重视平台维护的额外开销。

在预配大量数据登陆区域之前,请查看域分解并确定哪些功能域是共享底层基础结构的候选项。

总结

业务功能建模可帮助你更好地识别和组织数据网格体系结构中的域。 它提供一个整体视图来让你了解数据和应用程序为业务带来价值的方式,同时帮助你优先考虑并专注于数据策略和业务需求。 你还可以将业务功能建模用于数据以外的领域。 例如,如果可伸缩性是一个考虑因素,你可以使用此模型来确定最关键的核心功能并为其制定策略。

一些从业者担心通过预先映射所有内容来生成目标状态体系结构是一种资源密集型的做法。 相反,这种做法可以提示你在将域加入新的数据网格体系结构时有机地识别域。 不要自上而下地定义目标状态,而可以自下而上地探索、试验并将当前状态转换为目标状态。 虽然这种提议的方法可能更快,但它也存在重大风险。 当问题开始出现时,你可能很容易陷入复杂的迁移或重新建模操作之中。 朝自上而下和自下而上这两个方向努力,然后不断地在两者之间找到契合点是更可取的方法。

下一步