流数据库——流处理平台在第1章中,我们介绍了一个将实时数据提供给消费者的简单用例。我们还介绍了连接器,以及它们如何将静态
在第1章中,我们介绍了一个将实时数据提供给消费者的简单用例。我们还介绍了连接器,以及它们如何将静态数据转换为动态数据(或事件流),然后将其发布到流处理平台中的主题中。
事件流现在可以被读取,但它们很可能还不符合消费者可用的格式。在进行分析处理之前,事件通常需要清洗和准备。此外,事件还需要通过添加上下文进行丰富,以便足够有用,可以从中得出见解。分析处理高度依赖于数据的准确性和可靠性。通过解决缺失值、不一致性、重复项和异常值等问题,可以提高数据质量,从而获得更可靠和准确的分析结果。
在图2-1中,事件数据的准备工作还可以显著影响分析查询的性能。通过优化数据布局、索引和分区,可以提高数据检索和处理的效率。这包括数据反规范化、列式存储和针对分析工作负载定制的索引策略等技术。良好准备的数据可以减少处理时间,并加快获得见解的速度。我们将在第4章讨论如何将分析数据提供给消费者时,介绍反规范化、列式存储和索引策略。
事件数据准备在确保数据治理和合规性方面也起着至关重要的作用。这包括执行数据安全措施、匿名化敏感信息以及遵守隐私法规。通过正确准备数据,组织可以维护数据完整性、保护隐私,并符合法律和道德要求。
总体而言,数据管道中的数据准备对于确保数据准确、一致和结构良好以进行有效的分析处理至关重要。它提高了分析结果的可靠性,改善了性能,并有助于提取有意义的见解。
在图2-1中,从“主题”到“目标”的虚线代表了流处理平台。流处理平台的作用是在到达目标数据存储之前,承担清洗、准备和丰富事件数据的任务,作为预处理步骤的一部分。
注意
在本书中,我们将事件数据的清洗、准备和丰富任务称为“转换”,它们在流数据管道中执行。
转换任务通常消耗大量资源并且处理密集。因此,最好在写入数据存储之前,作为数据管道中的预处理步骤来完成转换。转换越早完成越好——因为逐步执行这些转换,只有少量数据需要同时处理,这比后来在静态数据中处理大量数据要少得多的资源消耗。
目标数据存储通常是在线分析处理(OLAP)数据存储。OLAP 数据存储允许用户对数据进行分析查询。实时 OLAP(RTOLAP)数据存储也是 OLAP,但它们经过优化以提供实时分析数据。
在提供分析数据给消费者的 OLAP 中,最好避免处理密集型任务。OLAP 需要保留资源以快速响应与业务相关的问题或为客户提供快速见解的分析查询——这也是尽早在管道中执行预处理的另一个原因。
注意
OLAP 是针对分析读取进行了优化的数据存储。它们通常是基于列存储的数据存储,用于为面向用户的仪表板和应用程序提供支持。OLTP 是捕获事件来源应用程序信息的数据库。它们针对写入和单行查找进行了优化。OLTP 数据库往往是第1章中提到的 CDC 提取的来源。
在我们的点击流用例中,我们将使用客户和产品信息来丰富点击流数据。这将为点击分析提供上下文信息,例如客户的位置、产品的类型、颜色等。这些信息可以帮助企业做出更精确的预测,从而大大减少时间、库存损失和客户满意度方面的成本。
一些转换足够复杂,需要记住信息,例如它们需要进行连接(如我们的用例)或聚合。这些信息需要存储在某个地方以便记住。这个地方被称为状态存储(state store)。这些复杂的转换因此被称为有状态转换(stateful transformations)。
有状态转换
在第1章中,我们讨论了将数据管道中的事件写入流处理平台中的主题。这使得事件保持在流中,供消费者订阅。不要将其与加载(L)或 ELT 中的“L”混淆。此时,我们从技术上讲所做的一切只是从源头提取事件并将其放入主题。至于 ELT,这仍然属于“E”(提取)阶段。
像 Kafka 这样的流处理平台并不会以可以保持状态的方式转换数据。因此,更复杂的转换(如聚合和连接)不能直接在 Kafka 上执行——你需要像 Kafka Streams 这样的额外组件。
数据管道遵循两种类型的模式,这些模式是常见的数据集成和处理方法,但它们在操作顺序上有所不同,并且在流处理能力上可能有限:
- 提取、转换和加载(ETL)
- 提取、加载和转换(ELT)
在 ETL 中,数据首先从源系统中提取,这些源系统可以是 OLTP 数据库、文件、设备或其他数据源。提取过程涉及从这些源中检索所需的事件。提取是我们在第1章中提到的源连接器的工作。
在 ETL 中,“T”要求流数据暂时存储在一个存储中。这个存储保持了转换的状态。换句话说,有状态转换需要在多个输入数据元素之间维护和更新一些信息或上下文。以下是几个示例:
- 滚动平均值 计算滚动平均值时,需要跟踪之前数据元素的总和和计数。随着新数据的到来,你会通过添加新值并移除最旧的值来更新状态,从而能够在滑动窗口内计算平均值。
- 会话化 在网络分析或事件处理中,会话化涉及根据特定标准(如用户在特定时间阈值内的活动)将相关事件分组为会话。要实现这一点,你需要维护有关正在进行的会话的状态信息,例如开始时间、结束时间和属于每个会话的事件列表。
- 去重 从流中删除重复事件通常需要维护以前看到的事件记录。随着新事件的到来,你可以将它们(通常使用主键)与存储的状态进行比较,以识别并过滤掉重复项。
- 窗口聚合 在数据窗口上进行的聚合(如求和、计数或最大值)需要保持状态,以在每个窗口内累积值。随着新数据点的到来,你会相应地更新状态,并定期生成聚合结果。
- 机器学习模型 在使用流数据持续更新和优化机器学习模型的场景中,模型本身需要状态。模型状态包含关于学习参数、权重或其他相关数据的信息,并随着每个新数据点的到来进行更新。
这些示例展示了在流处理转换中维护状态如何实现跨多个数据元素的计算,从而能够对流数据进行更复杂且有意义的分析。纯粹的流处理平台(如 Kafka)无法执行这些操作,除非部署了基于 Kafka Streams 的微服务等附加生态系统组件。
注意
一些流处理平台内置了无状态转换。这些转换被称为函数或单消息转换——不需要维护状态的转换。这些转换包括字符串转换(如大写转换)或列之间的简单数学运算。它们不属于 ETL 或 ELT 中的有状态转换。
如前所述,我们只完成了数据提取的“E”部分。仅仅将事件放入主题中不算是 ETL 或 ELT 中的“加载”,因为纯粹的流处理平台无法执行有状态转换。此外,纯粹的流处理平台不能直接为面向用户的消费者或应用程序提供服务。请记住,这些消费者需要对事件进行清洗、准备和丰富——而这些步骤在事件最初进入流处理平台时尚未完成。
这时,流处理平台就派上用场了。请注意,在本书的其余部分中,我们将流处理平台、流处理系统、流处理框架和流处理器这些术语交替使用。流处理平台具有保持状态和执行复杂转换的机制。
这些有状态的转换存在于数据管道中。我们将提取、转换和加载(ETL)到 OLAP 数据存储中称为数据管道。在我们的案例中,这是一个流数据管道(流 ETL)。数据管道在实时分析中起着至关重要的作用。它们负责从各种来源收集数据,将其转换为可以分析的格式,并及时传递给分析工具和应用程序。
数据管道
延续第1章中引入的水的比喻,流数据管道就像你家中的水管。在图2-2中,你家中的水管中的水可能含有矿物质,需要经过过滤或加热才能供用户使用。就像水管一样,流数据管道会将事件数据通过一系列转换,然后再传递给分析消费者。
数据管道的一个作用是将数据从操作数据平面移动到分析数据平面。操作数据平面是应用程序所在的地方,包括微服务和 OLTP 数据库。分析数据平面则是分析系统所在的地方——例如数据仓库、数据湖、湖仓,以及各种 OLAP 数据存储。数据管道位于操作数据平面和分析数据平面之间,分别将数据从一个平面转换并集成到另一个平面。见图2-3。
一旦数据被提取出来,它会经过之前提到的转换任务,以将其转换为适合目标系统、数据仓库或 OLAP 数据存储的格式(见图2-4)。转换后的数据通常会暂时存储在一个中间存储中。
最后,在 ETL 中,加载操作将转换后的数据加载到目标系统中,例如数据仓库。这涉及将数据插入到目标系统中的适当表或结构中。
让我们回到之前的简单用例,即客户在应用程序上点击了一件绿色T恤。图2-5展示了我们目前的情况。在左侧,我们捕获来自手机应用程序的数据。点击事件被发送到一个微服务,微服务将事件转发到流处理平台中的一个主题(“点击事件主题”)。
产品和客户信息被发送到 OLTP 数据库。箭头从手机指向 OLTP 数据库,表示在客户或产品上执行的事务。事务可以是插入、更新或删除操作。这些事务与我们在第1章中讨论的 CDC(变更数据捕获)相关联。OLTP 数据库中 WAL 中的事务由连接器消费,并发布到相应的主题中(“产品主题”,“客户主题”)。
点击事件、产品和客户的所有三个主题都由流处理器消费,该处理器实现了事件的有状态转换。流处理器的结果被发布到汇主题中,然后由 OLAP 数据存储消费。OLAP 数据存储随后将分析数据提供给数据分析师的仪表板。
正如你在图2-5中看到的,ETL 很好地支持流处理,因为转换是在流处理平台中完成的。毕竟,数据是保持动态的。转换在将数据加载到为消费者提供数据的目标存储(或 OLAP)之前完成。此方法避免了在目标数据存储中为每个查询重复执行(预)处理。要记住,预处理任务是资源密集型的。在数据服务存储中,我们需要保留这些资源来服务数据,而不是转换数据。
ELT 的局限性
在 ELT 中,转换和加载任务的顺序被颠倒了,这使得这种方法更加灵活,但也带来了一些限制。转换是在目标系统中执行的,而不是在数据管道中进行转换。由于不需要保持转换的状态,ELT 数据管道要简单得多,并且不使用有状态流处理。通过将数据加载到目标系统中(很可能是可以执行转换的数据库),数据已从流中移出并处于静止状态。数据管道不再被视为实时的,因为转换需要被安排或触发在某个时间间隔内运行。这种方法被视为批处理。
在目标数据存储上触发 SQL 语句运行。该 SQL 语句包含转换逻辑,这就是 ELT 末尾的“T”。让我们深入探讨这一点。
图2-6展示了 ELT 过程:
- 数据从 OLTP 数据库中提取。
- 数据加载到 OLAP 数据存储中。
- 数据加载完成后,执行用于转换数据的 SQL 语句。
在目标数据存储中,只有在“加载”完成后,SQL 语句的调用才会被触发。这意味着通过数据管道流动的数据是批处理的,因为批处理有一个结束点。如果数据是流式的,它将永远不会结束,因此,很难确定何时需要执行 SQL 语句。请参见图2-7。
在实时流处理的用例中,数据管道应延迟将数据持久化到目标存储,直到转换完成并且数据准备好供使用。乍一看,ELT 并不适合流处理。
使用 ELT 进行流处理
然而,ELT 也有一种方法可以支持实时流处理用例。这只能通过利用现代流处理平台和实时数据处理框架的能力来实现。以下是 ELT 如何应用于实时流处理用例的方式:
- 提取 在 ELT 中,提取步骤涉及从流数据源(如消息队列、事件流或实时数据源)检索数据。这些源会持续地实时生成数据,ELT 可以提取这些数据流以进行进一步处理。
- 加载 提取的数据被加载到支持流数据摄取和存储的目标系统中。这可以是一个流处理平台或数据存储,旨在实时处理高速度和高容量的数据流。目标系统应该能够有效地摄取流数据,并以一种允许实时处理的方式存储数据。
- 转换 在 ELT 中,转换步骤发生在数据加载到目标系统之后,例如使用像 Apache Flink、Apache Kafka Streams 或任何有状态流处理平台这样的实时数据处理框架。
图2-8展示了如何使用流处理平台作为目标来实现 ELT。在这种情况下,流可以是从 OLTP 数据库提取数据的连接器,也可以是像 Kafka 这样的流处理平台。然而,由于许多流处理平台(如 Flink)没有持久层(不包括它们的状态存储),转换步骤的结果需要被传输到例如数据库中,以便进行查询。流数据库具有持久层,也可以是启用这种架构模式的目标系统。我们将在第5章讨论流数据库时再次探讨这一点。
通过采用流处理平台和有状态流处理器,ELT 可以有效地处理实时流处理用例。在选择 ETL 和 ELT 之间的关键因素包括目标系统的可扩展性和性能、有效的流数据摄取能力以及在流数据上执行有状态转换和分析的能力。
流处理器
流处理器是用于实时处理连续数据流的软件平台或工具。最重要的是,它们能够执行有状态的转换,因为它们内置了状态存储。这些事件数据的转换对于消费者提取他们所需的分析见解是必要的。
流行的流处理器
以下是一些流行的流处理器:
- Apache Kafka Streams 是一个用于基于 JVM 的编程语言的流处理库,是 Apache Kafka 项目的一部分。它允许开发人员构建实时应用程序和微服务,这些应用程序和微服务可以从 Kafka 消费、处理并生成数据流。
- Apache Flink 是一个支持批处理和流处理的流处理器,它可以连接到各种来源和汇,例如 Kafka、Pulsar 和 Kinesis,以及 MongoDB 和 Elasticsearch 等数据库。Flink 将批处理视为流处理的一种特殊情况(带有有界数据的流处理)。与 Kafka Streams 相反,Flink 不是一个库,而是运行在其自己的集群上。
- Spark Structured Streaming 是 Apache Spark 的一个组件,支持流处理。它支持各种连接器,并且也是基于集群的。与 Kafka Streams、Flink 和 Samza 等其他流处理器不同,它使用微批处理而不是原生流处理——对于 Spark 来说,流处理是批处理的一种特殊情况,而在 Flink 中则相反。
- Apache Samza 是 LinkedIn 开发的一个流处理器。它支持 Kafka、Azure Event Hubs、Kinesis 和 HDFS,并且像 Flink 一样是基于集群的。
- Apache Beam 本身不是流处理器,而是一个统一的编程模型和一组用于构建数据处理管道的软件开发工具包(SDK)。它提供了一个抽象,使开发人员能够编写数据处理作业,这些作业可以在各种分布式处理引擎上执行,例如 Apache Flink、Apache Spark、Apache Samza 和 Google Cloud Dataflow。
新型流处理器
我们继续介绍一些新型流处理器:
- Quix Streams 一个基于 C#/Python 的流处理库,类似于适用于 JVM 的 Kafka Streams。Quix Streams 还支持流数据帧,这些数据帧的行为类似于 Pandas 或 Spark 中的数据帧,同时在底层进行增量更新。
- Bytewax 一个基于 Python 的流处理库,类似于 Kafka Streams,使用及时数据流(timely dataflow)作为底层流处理引擎。
- Pathway 一个基于 Python 的流处理库。它基于差分数据流(Differential Dataflow, DD)作为底层流处理引擎。
- Estuary Flow 一个支持多种连接器的流处理器。它是基于集群的。
这些流处理框架提供了诸如事件时间处理、窗口化、状态管理、容错、可扩展性以及与各种数据源和汇的集成等功能。它们使开发人员能够构建实时数据处理管道,并使应用程序能够在数据到达时做出反应,从而成为处理各种用例中流数据的宝贵工具。
注意
这些列表只包括流处理器,不包括流数据库。流数据库也可以执行有状态转换。我们将在第5章介绍流数据库。
尽管这些流处理器非常强大,但并非所有的流处理器都支持物化视图。物化视图以一种类似于数据库的方式表示数据,这种功能在实现实时分析用例时非常有用。
在撰写本文时,上述列表中的以下流处理器支持物化视图:
- Kafka Streams(KTable, GlobalKTable)
- Samza(Table)
- Pathway(Table)
在 Apache Spark 中模拟物化视图
截至本书发布时,据我们所知,Apache Spark 并不内置支持创建物化视图。然而,Apache Spark 提供了各种功能和优化,可以帮助实现与物化视图类似的效果。例如:
- 你可以利用 Spark 的缓存机制来缓存昂贵计算的中间结果或最终结果。通过将结果缓存到内存或磁盘,后续查询可以访问预计算的数据,从而可能提高性能。
- 在 Spark 中的另一种方法是使用 DataFrame 或 Dataset 来定义可重用的视图或转换,这些视图或转换可以应用于输入数据。这些视图可以保存并在多个 Spark 应用程序中重用,提供了一种数据抽象和优化的形式。
- 此外,与 Flink 和其他流处理器类似,Spark 可以与外部数据存储和系统(如 Apache Hive、Apache HBase 或其他数据库)集成,这些系统可能原生支持物化视图。在这种情况下,你可以利用底层数据存储的功能来创建和管理物化视图,同时使用 Spark 进行数据处理和分析任务。
值得注意的是,Apache Spark 生态系统在不断发展,新的功能和增强可能会在新版本中引入,以扩展其功能。因此,建议始终参考官方 Apache Spark 文档和发行说明,以获取关于物化视图或类似优化的最新信息。
两种类型的流
为了更好地理解物化视图,你需要了解流处理器中的流类型。在流处理器中流动的实时数据流有两种类型——变更流和仅追加流。描述这些流的最佳方式是提供它们如何创建的示例。参见图2-9。
在图2-9中,主题被突出显示:点击事件、产品和客户。点击事件流是仅追加的,这意味着它包含离散的、独特的事件。我们为什么知道这一点?因为每个点击都是独一无二的,即使是在同一件T恤上由同一客户进行的点击,它们之间的区别仅在于点击的时间。在仅追加流中,事件与一个时间戳相关联,该时间戳指示每个事件发生的时间。时间戳提供了时间信息,允许对流内的事件进行排序和序列化。这也适用于其他类型的事件,而不仅仅是点击事件。
仅追加流往往不是来源于数据库。在我们的用例中,如图2-9所示,点击流数据被发送到一个充当主题代理的微服务。如果点击事件被写入OLTP数据库,由于每个点击事件都是独特的,数据库将很快耗尽空间;也就是说,我们将触发对OLTP表的每次点击进行插入。因此,使用OLTP数据库来处理点击事件将是一个不好的设计——在这里显然更适合使用仅追加事件流。
相反,变更流数据几乎总是来自CDC事件。如果你还记得,这些事件是应用于OLTP数据库中的表的事务。这些事务包括插入、更新和删除操作。这些记录的增长速度不会像点击流数据那样快,因为有些事件会包括表中现有记录的更新或删除。
此外,客户数据可能不会频繁变化。客户可能会更改他们的姓名、电子邮件或电话号码,但这可能不会发生得太频繁。产品会有更多的变化,但与应用程序上的点击相比,仍然不多。此外,变更流往往代表对维度数据的更改。维度在数据库中变化缓慢,因为它们通常代表的属性是对其描述的实体不频繁或迅速变化的属性。
如果产品和客户数据集适合存放在OLTP数据库中,这意味着它们也应该适合存放在流处理平台的状态存储中,前提是状态存储大小合适。这为在流处理器中创建物化视图提供了一种方法,我们可以用它来丰富点击流数据。
在第1章中,我们讨论了OLTP数据库如何通过将主数据库复制到辅助数据库来支持灾难恢复。这正是我们在这里所做的——我们将OLTP数据库中的一个表复制到了流处理平台的状态存储中。
在流处理平台中,变更流和仅追加流将驻留在不同的结构中,这些结构的名称取决于你使用的流处理器。对于仅追加流,这些结构可能称为“streams”(流)。对于变更流,它们可能被称为“tables”(表)。我们可以使用SQL对点击流进行丰富化处理。
仅追加流
首先,示例2-1从Kafka中摄取点击流数据到一个假设的流处理器(在示例中,我们使用了类似于现有流处理器的语法)。这个语句将创建一个名为click_events的源表,这是一个仅追加流。
示例2-1:从Kafka主题创建源表
CREATE SOURCE click_events (
id integer,
ts long,
url varchar,
ipAddress varchar,
sessionId varchar,
referrer varchar,
browser varchar
)
WITH (
connector='kafka',
topic='clicks',
properties.bootstrap.server='kafka:9092',
scan.startup.mode='earliest'
)
ROW FORMAT JSON;
时间戳。
包含要解析的产品ID。
识别客户的ipAddress。
Debezium变更数据
示例2-2和2-3中的SQL语句也从Kafka中摄取数据——但在这种情况下,是用于产品和客户信息的Debezium CDC数据。Debezium是一个流行的连接器,可以读取OLTP数据库的WAL,捕获对表的更改并将其发布到Kafka中。在这些SQL语句中,可以注意到有before、after和op,它们提供了更改前后的值以及执行的操作类型。
示例2-2:摄取并为产品创建表
CREATE SOURCE products (
before ROW<id long, name varchar, color varchar, barcode long>,
after ROW<id long, name varchar, color varchar, barcode long>,
op varchar,
source <...>
)
WITH (
connector='kafka',
topic='products',
properties.bootstrap.server='kafka:9092',
scan.startup.mode='earliest'
)
ROW FORMAT JSON;
示例2-3:摄取并为客户创建表
CREATE SOURCE customers (
before ROW<id long, name varchar, email varchar, ipAddress varchar>,
after ROW<id long, name varchar, email varchar, ipAddress varchar>,
op varchar,
source <...>,
)
WITH (
connector='kafka',
topic='customers',
properties.bootstrap.server='kafka:9092',
scan.startup.mode='earliest'
)
ROW FORMAT JSON;
为了用产品和客户信息丰富点击流数据,我们需要将这三个表连接在一起。需要进行大量转换才能将CDC数据结构化,以便我们能够轻松地将其与点击流数据连接起来。现在,我们假设已经完成了这些工作。在我们开始使用流数据库时,我们将在后续章节中更具体地讨论这一点。
如果我们已将产品和客户表从Debezium格式转换为标准表,我们仍然无法将它们与点击流表连接起来。由于对单个记录进行了多次更改,产品和客户表将包含每个ID的重复记录。这意味着将这些表连接在一起会产生更多的重复记录。在表2-1中,你可以看到color值被多次更改。我们希望这个表只投影出最新的记录。这将只为每个ID投影一条记录。
表2-1:包含color列之前更改的产品表
ID | Name | Color | Barcode |
---|---|---|---|
1 | T-shirt | Green | 123456 |
1 | T-shirt | Greenish | 123456 |
1 | T-shirt | Lime green | 123456 |
物化视图
“物化”的定义是指自行创建的东西。通常,进行物化的“东西”是自己完成的。这一概念在理解物化视图时非常重要。
在示例2-4中,我们为每个CDC数据集创建了物化视图:产品和客户。每个物化视图只保留每条记录的最新版本。物化视图减少了记录的数量,只保留每个产品或客户ID的最新记录。这本质上就是物化视图的作用——它是对变更流的简化。简化是一种聚合,如计数、平均值、最小值、最大值等。在我们的例子中,物化视图通过ID简化了记录,捕获了记录的最新状态。
示例2-4:从Kafka主题创建源表
CREATE MATERIALIZED VIEW mv_products AS select * from products;
CREATE MATERIALIZED VIEW mv_customers AS select * from customers;
物化视图允许我们通过只投影每个产品和客户变更流的最新记录来将它们与点击流事件连接。我们不在点击流上创建物化视图,因为它不能被简化。请记住,仅追加流是离散的、独特的事件,如点击流。点击事件不能再进一步简化。示例2-5展示了我们如何将这三个表连接并将它们写入汇主题。
示例2-5:从Kafka主题创建源表
CREATE SINK http_enrich AS
SELECT
E.*,
C.*,
P.*
FROM click_events E
JOIN CUSTOMERS C ON C.ip=E.ip and
JOIN PRODUCTS P ON P.product_id=E.product_id
WITH (
connector='kafka',
topic='click_customer_product',
properties.bootstrap.server='kafka:9092',
type='upsert',
primary_key='id'
);
产品ID值从点击URL中提取并放置到名为product_id的单独列中。
由于变更流可以被简化,它们的结果足够小,可以放入流处理平台的状态存储中。
在将流数据加载到用于服务的OLAP数据存储之前,先对流进行这些转换是有利的。在OLAP上调用的消费者查询应仅包含分析业务逻辑,而不是在预处理中实现的任何转换。
转换事件的查询逻辑应与专注于业务分析的查询分开。我们将使用这种实践,通过使用推送查询和拉取查询在查询中将转换逻辑与分析逻辑分开。我们将在第4章中详细讨论物化视图和推送与拉取查询的区别。
从现在开始,我们将专注于支持构建物化视图的流处理器。流处理器中的物化视图可以像数据库中的物化视图一样处理。流处理器中的物化视图与数据库中的物化视图的主要区别在于,流处理器中的数据来源于流数据,而物化视图是持续更新的,而不是定期/手动更新的。
在图2-10中,我们可以看到已经完成的转换。这些转换是在流处理平台中定义的SQL并执行的。产品和客户的物化视图始终在运行,生成来自Debezium变更流的最新记录。
总结
在本章中,我们讨论了数据转换的常见方法以及这些转换在不同的数据管道模式中如何执行:ETL 和 ELT。我们指出,为了执行更复杂的转换,流处理器需要能够存储状态。
- 流处理平台需要支持有状态的流处理,以保持复杂的、有状态的转换的状态。
- ETL 自然适合流处理用例,因为它在数据到达服务数据存储之前进行预处理。
- ELT 在转换数据之前将事件写入目标数据存储。转换被定义为需要在目标数据库中触发执行的 SQL 语句,这强制了批处理语义。
- 通过将目标系统更改为流处理平台,ELT 可以支持流处理。
- 物化视图使得在流处理平台中实现非平凡的、有状态的转换成为可能。物化视图需要一个能够保存转换状态的流处理平台。
- 有状态的流处理平台将转换结果写入一个汇主题中。
在下一章中,我们将讨论将转换后的数据提供给消费者的不同方式。
转载自:https://juejin.cn/post/7402458172173058084