《构建事件驱动的Data Mesh》第一章:事件驱动的数据通信

144 阅读40分钟

第一章:事件驱动的数据通信

企业与数据的关系正迅速发生变化。过去,所有业务数据都可以整齐地存储在一个关系数据库中。但是,二十多年前开始的大数据革命已经发展演变,仅仅将海量数据存储在大数据湖中进行批量分析已不再足够。速度和互联性已成为下一个重要的竞争业务要求,再次改变了企业创建、存储、访问和共享重要数据的方式。

数据是企业的命脉。但是,许多企业创建、共享和使用数据的方式是杂乱无章、不协调的。数据网格提供了一个全面的框架,用于重新审视这些常常存在问题的关系,并提供了一种新的思考、构建和共享数据的方式,以便我们可以为客户提供更好的服务、无误的报告、可操作的洞察力,并实现真正的数据驱动过程。

为了理解我们试图解决的问题,首先需要了解现代企业面临的主要数据问题。

首先,支撑公司业务分析引擎的大数据系统变得庞大而复杂。已经有许多尝试来解决和减少这种复杂性,但它们都没有达到预期效果。

其次,大型企业的业务操作早已超越了单个巨型部署的范畴。多服务部署是常态,包括微服务和面向服务的架构。这些模块化系统的边界很难定义,特别是当许多独立的操作和分析系统都依赖于对相同数据集的只读访问时。这里存在一种对立的张力:一方面,将业务功能放置在单个应用程序中可以提供对该系统中生成和存储的所有数据的一致访问。另一方面,除了需要对重要业务数据进行共同的只读访问外,这些业务功能可能完全没有关联性。

第三个问题是在运营和分析领域都普遍存在的问题:无法访问高质量、有良好文档、自我更新和可靠的数据。组织处理的数据量每年都大幅增加,这加剧了对更好的排序、存储和使用数据的需求。这种压力对将所有内容都保留在单个数据库中的理想构成了最后一击,迫使开发人员将巨型应用程序拆分为独立的部署,并拥有自己的数据库。与此同时,大数据团队难以跟上这些运营系统的碎片化和重构,因为他们仍然独自负责获取自己的数据。

历史上,数据一直被视为二等公民,是业务应用程序排放的一种副产品。这种以应用程序为中心的思维方式仍然是当今计算环境中的主要问题源,导致临时性数据管道、拼凑在一起的数据访问机制以及不一致的类似但不同的真实性来源。数据网格直接应对了这些缺点,通过根本改变我们与数据的关系。数据和对数据的访问被提升为与任何其他业务服务平等的一等公民。

重要的业务数据需要作为构建应用程序的基本构建块原语,无论应用程序的运行时、环境还是代码库如何。我们将数据视为一等公民,具有专属所有权、最低质量保证、服务级别协议(SLA)以及用于干净可靠访问的可扩展机制。事件流是为服务这些数据的理想机制,为组织中可靠传递重要业务数据提供了一种简单而强大的方式,使每个消费者都能访问和使用他们所需的数据原语。

在本章中,我们将了解塑造我们今天常用的运营和分析工具和系统的力量以及伴随而来的问题。当我们谈论数据网格作为一个整体时,这些当代数据架构的巨大低效性为我们提供了丰富的经验教训,我们将将其应用于我们的事件驱动解决方案。这将为下一章打下基础。

什么是Data Mesh?

数据网格由Zhamak Dehghani发明。它是数据在组织中创建、访问和共享方式上的社会和技术转变。数据网格为讨论不同团队、领域和服务的需求和责任提供了一种共同语言,以及如何共同努力使数据成为一等公民。本章探讨了构成数据网格基础的原则。

在我的上一本书《构建事件驱动微服务》(O'Reilly)中,我介绍了数据通信层这个术语,涉及到了与数据网格许多相同的原则:将数据视为一等公民,为领域间通信形式正式化结构,将数据发布到事件流中供通用使用,并使数据的生产者和消费者都能轻松使用。虽然我喜欢数据通信层的术语,但现实情况是,我认为数据网格的语言和正式原则提供了我们在讨论这个问题时所需的一切,而无需引入另一个“数据某某某”的范式。

Dehghani的书《Data Mesh》(O'Reilly)深入详细地展示了数据网格的理论和思想领导力,但对具体实现保持中立。

在本书中,我们将介绍一个实际的数据网格实现,其中事件流作为领域间数据通信的主要数据产品模式。我们可以更加务实,在理论上更具体和具体地实现事件驱动设计。虽然我认为事件流基本上是领域间通信的最佳选择,但它们也具有权衡,并且我当然也会涵盖这些权衡,并在适合的情况下提到非流式可能性。

数据网格基于四个主要原则:领域所有权、数据作为产品、联邦治理和自助平台。这些原则共同帮助我们在整个组织中构建重要业务数据的通信方式。在下一章中,我们将更详细地评估这些原则,但在此之前,让我们看看为什么数据网格在今天如此重要。

事件驱动的Data Mesh

现代大数据的竞争要求,结合现代云计算,需要重新思考企业如何创建、存储、传输和使用数据。这种新数据架构的基础是事件,即代表实际业务活动的数据量子,通过多种专用事件流提供。事件流为创建中枢神经系统提供了手段,使业务单位能够访问和使用基本的、自动更新的数据构建模块。这些数据构建模块与容器化、基础设施即服务(IaaS)、持续集成(CI)和持续部署(CD)流水线以及监控解决方案等组件一起,构成了现代云应用的基础。

事件流并不是新概念。但是,许多以前的事件驱动架构所依赖的技术限制,如有限的规模、保留和性能,已经在很大程度上得到缓解。现代的多租户事件代理配备分层存储,可以存储无限量的数据,消除了限制以前架构的严格容量限制。数据生产者将重要的业务领域数据写入事件流中,使其他人可以在该流上耦合并使用数据构建模块进行应用开发。最后,消费者应用程序可以创建自己的事件流,与他人共享自己的业务数据,从而形成一个标准化的通信网格供所有人使用。

数据网格为我们构建这个互联的中枢神经系统提供了非常有用的概念和语言。图1-1展示了数据网格可能的基本示例。

image.png

拥有运营系统Alpha的团队选择了一些来自其服务边界的数据,对其进行重建,并将其写入他们自己拥有的源对齐的数据产品中(我们将在《三种数据产品对齐类型》中详细介绍数据产品对齐)。拥有运营系统Beta的团队从这个数据产品中读取数据到他们自己的服务边界,再次进行重建、转换,并仅存储他们需要的部分。

同时,第三个团队连接到Alpha团队的数据产品,并使用它来组合自己的聚合对齐的数据产品。然后,这个团队使用其聚合对齐的数据产品来支持实时流分析,并将一批文件写入云存储,数据分析师将使用这些数据来生成报告并支持现有的基于批处理的分析任务。

这个图表只是数据网格的冰山一角,还有许多领域需要涵盖。但事件驱动的数据网格的核心思想是让数据实时可用,供任何需要的消费者使用。

数据网格解决的许多问题已经存在很长时间了。现在我们将进行一个简短的历史回顾,以更好地理解我们要解决的问题,以及为什么数据网格是一个非常相关和强大的解决方案。

在操作平面中使用数据

数据往往是由执行业务操作的操作系统创建的。最终,这些数据往往会被提取到分析平面用于分析和报告的目的。在本节中,我们将重点关注操作平面的一些内容以及与其他操作(和分析)服务共享业务数据的常见挑战。

数据单体架构

在线事务处理(OLTP)数据库构成了当今大部分操作计算服务的基础(为简单起见,我们将其称为“单体”)。单体系统在操作层面通常扮演重要角色,因为一致性同步通信比异步通信更容易理解和开发。关系数据库,如PostgreSQL和MySQL,在单体应用中得到广泛应用,提供原子性、一致性、隔离性和持久性(ACID)事务和应用的一致状态。

应用程序和数据库共同展示了以下单体数据原则:

  1. 数据库是真相的来源 单体依赖底层数据库作为应用程序信息的持久存储。任何新记录或更新记录首先都要记录到数据库中,使其成为这些实体的确定性来源。
  2. 数据具有强一致性 当单体的数据存储在典型的关系数据库中时,它具有强一致性。这为业务逻辑提供了强大的读写一致性,并且借助事务,它不会无意中访问部分更新的记录。
  3. 只读数据可随时获取 存储在单体数据库中的数据可以被单体的任何部分轻松访问。只读访问权限确保数据不会被无意中修改。

请注意,数据库应仅由拥有它的服务直接访问,而不应作为集成点。

这三个原则形成了单体架构的绑定力量。你的应用代码对存储在单体数据库中的整个数据范围具有只读访问权限,作为一组权威、一致且可访问的数据原语。这个基础使得在同一应用程序中构建新的应用功能变得容易。但是,如果你需要构建一个新的应用程序呢?

在操作层面上,将数据进行通信存在一些困难

新的应用程序无法像构建为单体应用程序的一部分那样轻松访问数据原语。如果新的应用程序不需要单体应用程序中的任何业务数据,那么这不会成为问题。然而,实际情况很少是这样,因为企业实际上是一组相互重叠的领域,特别是共同核心领域,其中相同的数据满足多个业务需求。例如,电子商务零售商可能依赖其单体应用程序处理订单、销售和库存,但需要一个由基于文档的数据库(或其他类型的数据库)驱动的新应用程序来实现纯文本搜索功能。图1-2突显了问题的关键所在:我们如何将数据从“可靠老兵”传输到新的文档数据库以提供搜索功能?

image.png

这使得新的搜索服务团队陷入了一些困境。该服务需要访问单体应用程序中的商品、店铺和库存数据,但同时也需要将其建模为一组文档以供搜索引擎使用。团队通常尝试通过两种常见方式来解决这个问题。一种方式是复制和转换数据到搜索引擎,试图保留三个单体应用程序数据原则。第二种方式是使用API来重构源系统的服务边界,使得数据不仅仅是简单地复制出来,而是完全由单个系统提供。这两种方法都可以取得一定的成功,但从根本上来说,它们都不足以作为一种通用解决方案。让我们详细看一下这些方法,以了解其原因。

策略1:在服务之间复制数据

这个策略下有几种机制可以采用。第一种也是最简单的方法是直接访问数据库,在需要时获取所需的数据。稍微结构化一些的方法是定期查询源数据库,并将结果集转储到新的结构中。虽然这样做可以让你选择一个不同的数据存储技术来支持新的服务,但也存在一些主要的缺点:

与源系统的紧密耦合

你仍然与源数据库的内部模型紧密耦合,并且完全依赖它来处理查询需求。

对源系统性能的负载

大规模数据集和复杂查询可能会导致数据库变得不稳定。尤其是在将数据去规范化以支持分析用例时,多表和复杂的连接操作很常见。

第二种常见的数据复制机制是源数据库的只读副本。虽然这可能有助于缓解查询性能问题,但消费者仍然与内部模型紧密耦合。而且,不幸的是,每增加一个对内部数据模型的外部耦合,都会增加变更对所有相关成员的成本、风险和难度。

随着每个新的独立数据源和每个新的所需副本,数据复制策略变得越来越难以维护。这引入了一些新问题:

原始数据集可能很难发现

一个团队可能意外地将其服务与原始数据的副本耦合在一起,而不是与原始数据本身耦合在一起。如果不借助非正式的知识网络,很难发现数据的原始来源是什么。

点对点连接的增加

此外,每个新的独立服务可能成为其自己的数据权威源,增加了服务间数据复制的点对点连接数量。

服务间的数据点对点复制引入了额外的复杂性,同时对源的内部数据模型产生了紧密耦合。这对于构建现代的数据通信层来说是不足够的。

策略2:使用API避免数据复制需求

直接耦合的请求-响应微服务,有时也被称为同步微服务,是处理访问远程数据的另一种常见方法。微服务可以直接调用另一个服务的API来交换少量信息并代表彼此执行工作。 例如,您可能有一个微服务负责管理与库存相关的操作,同时您还有其他专门处理发货和账户的微服务。每个服务的请求都来自专用的移动前端和Web前端微服务,它们将操作串联起来并向用户返回无缝视图,如图1-3所示。

image.png

同步微服务具有许多优点:

  1. 针对业务领域的需求构建专用服务。
  2. 所有者具有高度的独立性,可以使用最适合其需求的工具、技术和模型。
  3. 团队还可以更好地控制其领域的边界,包括控制和决策如何扩展边界以满足其他客户的需求。

有许多关于同步微服务的书籍,例如《Building Microservices》(作者:Sam Newman,O'Reilly出版社)和《Microservices Patterns》(作者:Chris Richardson,Manning出版社),它们提供了比我在这里提供的更详细的信息,因此我在这里不会详细展开。

该策略的主要缺点与单个服务的缺点相同:

  1. 在微服务的API中,没有简单可靠的机制来访问数据。
  2. 同步微服务通常是为提供业务操作的API而构建的,而不是为底层领域提供可靠的批量数据访问。
  3. 大多数团队都采用与单体应用程序相同的备选方案:根据需要直接从数据库中获取所需的数据(参见图1-4)。

image.png

在这个图示中,新服务依赖于库存、账户和配送服务,只是为了访问底层的业务数据,而不是执行任何业务逻辑。虽然这种形式的数据访问可以通过同步API提供,但并不适用于所有的用例。例如,大规模的数据集、时间敏感的数据和复杂的模型可能会阻止这种类型的访问成为现实。此外,还需要承担提供数据访问API和数据服务性能的运营负担,除了基本微服务功能之外。

运营系统缺乏一种通用的解决方案,用于在服务之间传递重要的业务数据。这不仅仅是运营领域的问题。大数据领域为分析、报告、机器学习、人工智能和其他业务服务提供支持,并对来自业务各个领域的完整数据集有着巨大需求。

虽然以突袭式数据访问的方式违反领域边界是构建大数据工程的基础(在我在这个领域度过的十年中,我参与过这样的突袭),但幸运的是,它为我们提供了丰富的见解,我们可以将其应用于为所有数据用户提供更好的解决方案。但在此之前,让我们看一下大数据领域对于访问和使用数据的要求,以及这个领域是如何发展到今天的状态的。

分析平面:数据仓库和数据湖

而运营关注点主要集中在OLTP和服务器间的通信上,分析关注点主要是回答有关业务整体表现的问题。在线分析处理(OLAP)系统以更适合分析查询的格式存储数据,允许数据分析师在不同维度上评估数据。数据仓库有助于回答诸如“去年我们销售了多少件商品?”和“我们最受欢迎的商品是什么?”这类问题。

回答这些问题需要将运营数据重新建模为适合分析的模型,并考虑到最终找到答案的大量数据。 将数据导入数据仓库的过程通常依赖于一种称为抽取、转换和加载(ETL)的过程,如图1-5所示。

image.png

定期安排的作业从一个或多个源数据库中提取数据,并将其转换为数据仓库所需的数据模型。然后将数据加载到数据仓库中,数据分析师可以进行进一步的查询和分析。数据仓库通常在写入时强制执行明确定义的模式,包括列类型、名称和可空性。

从历史上看,数据仓库在提供分析结果方面被证明是成功的。但是,不断增加的数据和计算负载需要更大的磁盘驱动器和更强大的计算芯片,最终遇到了计算机硬件的物理限制。因此,与其进一步扩大规模,更好的选择是扩展规模。 对于谷歌来说,对大规模的需求是显而易见的,他们于2003年10月发布了《谷歌文件系统》。这个时代见证了大数据的诞生,引发了全球范围内对我们如何创建、存储、处理和最终使用数据的巨大重新思考。

Apache Hadoop迅速成为解决传统OLAP系统面临的扩展问题的明确方法。因为它是免费且开源的,任何公司在任何地方都可以使用它,只要你能找出如何管理基础设施需求。它还提供了一种新的计算分析方式,不再受限于资源有限的专有系统。 Hadoop引入了Hadoop分布式文件系统(HDFS),这是一个持久性和容错性的文件系统,可以创建、存储和处理跨多个普通硬件节点的大规模数据集。

虽然HDFS现在已经大部分被Amazon S3和Google Cloud Storage等选项取代,但它为一个大胆的新想法铺平了道路:将所有所需的数据复制到一个逻辑位置,无论大小如何,并应用处理来清理、整理和重新建模数据,以满足重要的业务分析需求。 大数据架构对数据的理念进行了重大转变。它不仅解决了现有OLAP系统的容量问题,还在数据世界引入了一个新的概念:使用非结构化或半结构化数据是可接受的,甚至更可取,而不是像数据仓库那样在写入时强制执行模式。在这个新的大数据世界中,你可以自由地以有或无任何模式或结构编写数据,并在查询时应用读取时的模式来解决所有问题。

许多数据工程师很高兴摆脱写入时的模式要求,因为这样可以更容易地将数据引入生态系统中。 请参考表1-1,比较关系数据库和MapReduce之间的数据结构和用例。MapReduce是一个早期的Hadoop处理框架,用于读取数据、应用模式(在读取时)、执行转换和聚合操作,并生成最终结果。

截屏2023-05-24 11.55.32.png

请注意,这份2009年的权威指南将MapReduce作为处理低完整性数据和动态模式的解决方案,并强调HDFS应该存储低完整性的非结构化数据,其中可能存在不同且可能冲突的模式,需要在运行时解决。它还指出,这些数据是写入一次,多次读取,这正是你希望有一个强大、一致、强制执行的模式的情况,以提供充分的机会让善意但不受约束的数据使用者应用读取时的模式来错误解释或使数据无效。

在写入时使用模式,包括定义良好的列,包括类型、默认值、空值可选性和名称,并不一定以任何方式限制下游转换。它也不会强制你在写入之前对数据进行反规范化或连接。 模式确实为您提供了一个理智检查,确保您所摄入的数据至少符合下游处理器的最基本期望。放弃这种理智检查会将错误的检测推迟到下游,给试图使用数据的人带来重大困难。 在Hadoop的早期,我认为我和其他许多人并没有真正意识到模式在读取时的概念将如何改变数据的收集、存储和分析方式。我们相信并支持这样的想法,即根据需要获取数据并在事后进行重构、清理和强制执行模式是可以接受的。

这对于那些考虑迁移到Hadoop以缓解其分析限制的人来说也非常有吸引力,因为这一举措并不限制您的写入过程,也不会让您因数据摄入的严格规则而感到困扰-毕竟,您可以在复制数据后修复数据! 不幸的是,将非结构化数据存储为在读取时使用模式的基本原则被证明是大数据革命引入的代价最高、最具破坏性的原则之一。让我们准确地看看这如何对分布式数据访问产生负面影响,以及为什么明确定义的模式化数据是数据网格的重要原则。

在读取时使用模式对组织产生的影响

在读取时强制执行模式,而不是在写入时强制执行,会导致所谓的“糟糕数据”的大量存在。缺乏写入时的检查意味着写入HDFS的数据可能不符合读取者在其现有工作中使用的模式,如图1-6所示。一些糟糕的数据会导致消费者停止处理,而其他糟糕的数据可能会悄无声息地未被发现。虽然这两种情况都是有问题的,但是悄无声息的失败可能是致命的,而且很难被发现。

image.png

为了更好地理解模式在读取时的破坏性影响,让我们看一下三个角色及它们之间的关系。虽然我的经验有限,但在我的职业生涯中,我有幸与许多其他数据人员交流过,他们来自不同的公司和业务领域。我可以自信地说,虽然各个组织的责任有所不同,但对于大多数使用大数据的当代组织来说,这些角色的概述基本上是普遍适用的:

数据分析师

负责回答业务问题、生成见解并创建数据驱动的报告。数据分析师查询由数据工程师提供的数据集。

数据工程师

负责从组织周围的系统中获取重要的业务数据,并将其转化为数据分析师可以使用的格式。

应用程序开发人员

负责开发应用程序以解决业务问题。该应用程序的数据库也是数据分析师工作所需数据的来源。

在过去,采用Hadoop的最常见方式是建立一个专门的数据团队,作为常规工程团队的子集或完全独立于其之外。数据工程师会访问应用程序开发人员的数据库,获取所需数据,并将其提取出来放入HDFS。数据科学家会对其进行清理和重构(可能还会基于此构建机器学习模型),然后将其传递给用于分析的部门使用。

最后,数据分析师会查询和处理捕获的数据集,以产生对他们的分析问题的答案。然而,这种模式导致了许多问题。数据团队和应用程序开发人员之间的交流很少,并且通常围绕着确保数据团队的查询负载不会影响生产服务能力。

这种关注点和责任的分离存在三个主要问题。让我们来看看它们是什么。

问题一:数据模型边界被违反

被摄入到分析领域的数据与源头的内部数据模型紧密耦合,并直接影响所有对该数据进行下游操作的用户。对于简单、很少发生变化的数据源,这可能不是一个大问题。但是,许多模型涵盖了多个表格,专门用于在线事务处理(OLTP)操作,并且可能需要进行大规模重构以适应业务用例的变化。对于这种内部模型的直接耦合将使所有下游用户都面临这些变化的影响。

问题二:缺乏单一所有权

应用程序开发人员是领域专家和源数据模型的主人,但他们往往没有责任将数据传达给其他团队(如大数据团队)。相反,他们的责任通常仅限于应用程序和数据库的边界。

与此同时,数据工程师的任务是找到一种方法在不影响生产系统的情况下及时从应用程序开发人员的数据库中提取数据。数据工程师依赖于数据源,但往往对数据源的处理过程没有太多影响力,使得他们的角色变得非常被动。生产和数据之间的分隔是许多组织中真实存在的障碍,尽管尽最大努力进行协商、集成检查和预防性工具的使用,但数据摄取管道的故障仍然是一个普遍的问题。

最后,数据分析师负责利用数据推导出业务价值,他们与领域专家(应用程序开发人员)之间相隔两个层级,如果在其中加入了数据科学家进一步处理数据,则相隔三个层级。分析师和数据科学家必须处理数据工程师能够提取的所有数据,包括解决不一致的数据,这些数据与其现有的读取模式不匹配。

由于数据分析师经常与其他数据分析师共享他们的模式,他们还需要确保他们解析的模式不会破坏彼此的工作。随着组织和数据的增长,这变得越来越困难,不幸的是,他们的解析努力仅有利于其他分析师。运营用例必须自行解决获取数据的问题。

问题三:自助和定制的点对点数据连接

在大型组织中,数据团队通常由数百或数千名成员组成,而在小型组织中,可能只有几个成员。对于大型数据组织来说,将相同的数据源拉入数据平台的不同子领域是常见的做法,具体取决于使用案例、团队边界和技术边界。

例如,销售数据可以被拉入分析部门、消费者报告部门和应收账款部门。每个子组通常都会独立创建、调度和执行ETL作业,将数据拉入自己的子领域,导致源数据的多个独立管理副本,如图1-7所示。

image.png

虽然定制的点对点数据连接可以让用户在需要时访问所需的数据,但它最终会导致混乱的纠缠。很难确定谁拥有ETL作业,特别是当用户和团队共享访问凭证时。追踪数据血统、数据的新鲜度和确定数据集的所有权同样困难,通常会导致新的ETL作业进一步扩散。毕竟,如果你不确定数据是否完全符合需求,为了安全起见,最好自己制作一个作业和副本。

在源数据上强制实施访问控制可以帮助澄清谁可以访问哪些数据,但仅限于主要源。但是,限制数据访问可能会适得其反。复杂或繁琐的获取访问权限过程可能导致人们从其他较不受保护的源复制数据。在图1-7中,可以看到Predictions领域通过从User insights领域复制销售数据来绕过源数据访问控制。

但是,这些副本是否真的是相同的数据呢?同步频率、数据转换、时区、间歇性故障和错误的环境(例如,使用的是暂存环境而不是生产环境)等问题可能会影响您复制的源数据的完整性。您可能认为自己获取了正确的数据,但实际上并非如此,而您并不知道。例如,您复制了一个数据集,认为它与UTC-0时间同步,但实际上它是与UTC-6同步的。数据的格式、分区和排序可能看起来完全相同,但这些难以检测和未记录的差异仍然存在。

定制的点对点连接可能难以维护,导致数据泛滥,并可能产生许多重复的同步作业,生成类似但不完全相同的数据。

这种分散的模型和数据所有权及分发的责任导致了糟糕的数据,这在时间、金钱和机会上都是昂贵的损失。在结束之前,让我们来看看这些问题的成本,并了解数据网格是如何解决这些问题的。

糟糕的数据:不采取行动的成本

糟糕的数据通常直到应用于模式时才被发现。例如,在数据库中无法将文本插入到Int32列中。然而,通过使用按需模式,我们有效地将数据验证推迟到数据传输过程的最后。尽管我们的数据源可能使用了模式,但无法保证我们无数个点对点的管道是否正确捕获了数据旁边的模式。有很多情况下,Int32被捕获为String,或者更糟糕的情况是Object。

修复糟糕的数据成本高昂,而且问题越普遍,成本越高。每个访问、使用、复制或处理数据的人可能都会受到影响,并且可能需要采取相应的纠正措施。复杂性进一步增加的原因是不同的数据使用者可能以不同的方式进行“修复”。这可能导致与其他数据结果不一致的差异性结果,并且难以检测、追踪和纠正。

糟糕的数据通常是无意中由善意的个人创建的,仅仅因为许多数据传输工具采用了点对点、“获取并抓取”的方式。这在大规模的情况下更加突出,其中一个团队发现他们的数据副本不仅是错误的,而且错误已经持续了几个月,每个使用该数据集计算的下游作业的结果也是错误的。这些作业可能使用数百或数千个处理节点,每个节点的RAM容量为32倍至128倍,每晚处理数百TB的数据。仅仅为重新运行所有受影响的作业的处理成本可能就达到了数十万甚至数百万美元。

业务决策也可能受到影响。我曾经了解过一个情况,其中一家公司对其客户的集体账单错误计费了数百万美元,有些客户过多收费,有些客户过少收费。导致这种情况的原因实际上非常无意,是模式更改与复杂的“获取并抓取”数据ETL链相结合,在读取时应用模式时出现了一些数据解释问题。只有当客户注意到他们的账单费用远远超过了他们的使用费用时,才开始展开调查并发现了根本问题。

数据在现代计算中的日益重要地位导致了其他人对相关成本进行研究,尤其是关于糟糕数据给企业带来了多大的成本。结果令人震惊地高。

根据哈佛商业评论(HBR)引用的IBM的一份报告(原始报告不再可用),在仅限美国范围内,糟糕数据的财务影响估计为3.1万亿美元。尽管原始报告现在无法获取,但HBR保留了一些相关数字:

  • 50% - 知识工作者浪费时间在寻找数据、查找和纠正错误以及搜索不信任的数据的确认来源上的时间。
  • 60% - 数据科学家估计花费在数据清洗和组织上的时间。

糟糕数据的问题已经存在很长时间。随着原始数据源的变化,数据副本发散。数据副本会过时。在一个数据集中检测到的错误在副本中并没有得到修复。与解释和理解数据相关的领域知识仍然不完整,原始数据的所有者也没有提供支持。

数据网格提出通过将数据提升为一流公民,像其他产品一样来解决这个问题。具有明确定义的模式、领域文档、标准化访问机制和服务级别协议的数据产品可以在源头大大减少糟糕数据的影响。一旦消费者与数据产品耦合,他们可能仍然会犯自己的业务逻辑错误,这是不可避免的。然而,在获取、理解和解释解决业务问题所需的数据时,他们很少会出现无意中的错误。无所作为并不是解决方案。

我们能否统一分析和运营工作流程?

工程领域中存在一个核心问题:不仅数据团队面临数据访问和质量问题,每个需要访问其他数据库中存储的数据的OLTP应用程序都面临相同的数据访问问题。那么,对于运营需求,如何访问嵌入在另一个服务中的重要业务数据呢?

为了改善服务之间的运营通信,已经尝试了几种方法,包括面向服务的架构、企业服务总线以及当然也包括点对点的请求-响应微服务。但在这些架构中,服务的数据被封装在自己的数据库中,其他服务无法访问。从某种程度上说,这是有益的,内部模型得到了保护,并且你有一个单一的真实数据源。应用程序提供操作API,其他应用程序可以调用这些API来代表其执行工作。然而,这些解决方案并未解决批量只读访问明确数据集的根本问题,以供自身的运营用例使用。

更复杂的问题是,现在许多运营用例依赖于分析结果。考虑机器学习、推荐引擎、人工智能等。某些用例(例如生成每月畅销产品报告)可以明确标记为“分析性的”,可以从定期计算的作业中获得。其他用例则不那么明确。比如,一家电子商务零售商希望根据当前库存(运营)、先前用户购买记录(分析)和用户实时估计的购物意向(分析和运营)来展示鞋类广告。实际上,在运营和分析之间的界限很少被清晰定义,并且完全相同的数据集可能需要用于多种用途,无论是分析、运营还是介于两者之间。

数据分析和传统的运营系统都很难访问其他数据库中的数据。随着数据的增加速度、速率和规模的不断增长,以及单个服务的计算限制达到后,系统被迫向外扩展而不是向上扩展,这些困难进一步加剧了。大多数组织的数据通信策略基于昨天的技术,并没有考虑到现代云存储、计算和软件即服务(SaaS)的提供。这些工具和技术改变了数据在组织内的建模、存储和通信方式,我们将在本书的剩余部分中对其进行更详细的探讨。

采用Data Mesh方式重新思考数据

数据网格解决方案的前提很简单。将重要的业务数据集发布到专门的、持久的、易于访问的数据结构中,称为数据产品。数据的原始创建者负责对数据进行建模、演化、质量控制和支持,将其视为组织中的任何其他产品一样予以优先关注。

潜在的数据消费者可以探索、发现并订阅他们在业务用例中所需的数据产品。这些数据产品应该描述清楚、易于解释,并构成一组自更新的数据原语,为业务服务和分析提供基础。

事件流在数据产品的构建中起到了最佳角色,因为它们提供了不可变、可追加、持久和可重放的基础,适用于组织中的所有消费者。这些流成为操作、分析和其他工作负载的基本真实数据源。

这种架构利用了现代云计算和软件即服务(SaaS),如第5章中更详细介绍的内容。一个良好的工程堆栈使得在整个应用程序生命周期中轻松创建和管理应用程序,包括获取计算资源、提供可伸缩性、日志记录和监控功能。事件流为现代工程堆栈提供了形式化和标准化的数据访问,以完成所需的工作。

让我们通过这个提案的视角重新审视前面在本章中介绍的单体数据原则。这三个原则概述了将新的业务功能放置在单体中的主要影响因素。一组自更新的事件流如何与这些原则相关联呢?

  • 数据库是真实数据的来源 → 事件流是真实数据的来源 现在,数据领域的所有者负责将外部可见的模型组合成一组事件,并将其写入一个(或多个)事件流。作为交换,其他服务将不再直接访问和依赖内部数据模型,生产者也不再负责代表查询服务提供定制的业务任务,这在微服务架构中经常发生。事件流成为系统之间的主要耦合点。下游服务从事件流中消费事件,根据自身需求对其进行建模,并将其存储在自己的专用数据存储中。

  • 数据具有强一致性 → 数据具有最终一致性 事件流生产者可以保持其自身内部状态的强读写一致性,同时享有其他数据库的优势,比如本地的ACID事务。然而,事件流的消费者在事件处理和状态建模方面是独立的,因此依赖于其自己的最终一致性视图。消费者无法对事件流进行写访问,因此无法修改数据源。消费者系统设计必须考虑到最终一致性,在本书的后面部分将对此主题进行更详细的探讨。

  • 只读数据可以轻松获取(保持不变!) 事件流提供了一种形式化的机制,以只读的、自更新的格式传递数据,消费者不再需要创建、管理和维护自己的提取机制。如果消费者应用程序需要保留状态,那么它可以使用自己的专用数据存储来实现,完全独立于生产者的数据库。

数据网格对组织内部数据的所有权边界进行了形式化,并标准化了存储和通信机制。它还提供了一个可重用的框架,用于生产、消费、建模和使用数据,不仅适用于当前的系统,还适用于尚未构建的系统。

总结

现有的数据通信策略在面对真实的业务需求时显得力不从心。通过越过服务边界来获取数据并不是一种可持续的做法,但这种做法非常普遍,通常支持多个关键系统和分析工作流程。将系统重组为整洁的模块化微服务并不能解决数据访问的问题;您的业务的其他部分,如大数据分析和机器学习团队,仍然需要从组织中的各个领域全面访问当前和历史数据。无论如何,数据的副本都将被创建,我们可以选择与此抗争,或者接受这个事实并努力改进。在选择后者时,我们可以使用事件流来标准化和简化数据在组织中的通信,将其作为自更新的单一真相来源。

事件构成事件驱动架构中的通信基础,从根本上塑造了我们解决问题的空间。通过事件流传递的事件构成了构建异步和反应式系统的基本组件。这些构建块类似于同步API:其他应用程序可以发现它们,耦合它们,并使用它们构建自己的服务。最终一致性、消费者特定模型、只读副本和流材化等概念将在本书中进行探讨,同时探讨现代云计算、存储和网络资源在这种新的数据架构中所起的作用。

接下来的章节将深入探讨构建和使用事件驱动数据网格。我们将探讨如何设计事件,包括状态、操作和通知事件,以及生成和消费事件的模式。本书还涵盖了大规模处理事件的内容,包括多集群和多区域,隐私和合规最佳实践,以及处理最终一致性和异步通信的原则。我们将探讨适应事件驱动数据网格所需的社会和文化变革,并查看一些实际案例研究,突出了其他人取得的成功和经验教训。

最后,我们还将研究您可以采取的实际步骤,以在您自己的组织中开始构建这个架构。这种架构最好的一点是它是模块化和渐进式的,您可以逐步利用其优势在业务的一个领域开始实施。虽然有一些最初的投资,但现代云计算和SaaS解决方案几乎消除了进入门槛,使得开始和测试这是否是合适的解决方案变得更加容易。