阿里云 Flink 原理分析与应用:深入探索 MongoDB Schema Inference

本文涉及的产品
实时计算 Flink 版,1000CU*H 3个月
简介: 本文整理自阿里云 Flink 团队归源老师关于阿里云 Flink 原理分析与应用:深入探索 MongoDB Schema Inference 的研究。

本文整理自阿里云 Flink 团队归源老师关于阿里云 Flink 原理分析与应用:深入探索 MongoDB Schema Inference 的研究,内容主要分为以下四部分:

  1. MongoDB 简介
  2. 社区MongoDB CDC 核心特性
  3. MongoDB CDC 在阿里云 Flink 实时计算产品的实践
  4. 总结

一、MongoDB 简介

MongoDB 是一种面向文档的非关系型数据库,支持半结构化数据存储;也是一种分布式的数据库,提供副本集和分片集两种集群部署模式,具有高可用和水平扩展的能力,比较适合大规模的数据存储。

MongoDB 使用了弱结构化的存储模式,支持灵活的数据结构和丰富的数据类型,适合 Json 文档、标签、快照、地理位置、内容存储等业务场景。它天然的分布式架构提供了开箱即用的分片机制和自动 rebalance 能力,适合大规模数据存储。另外, MongoDB 还提供了分布式网格文件存储的功能,即 GridFS,适合图片、音频、视频等大文件存储。

二、社区 MongoDB CDC 核心特性

Flink CDC 是基于数据库的日志 CDC(Change Data Capture)技术,实现了全量和增量的一体化读取能力,借助 Flink 优秀的管道能力和丰富的上下游生态,支持实时捕获、加工多种数据的变更并输出到下游,MongoDB 也是支持的数据库之一,支持的主要特性包括:

  • 支持 Exactly-once 语义
  • 支持全量、增量订阅
  • 支持 Snapshot 数据过滤
  • 支持从检查点、保存点恢复
  • 支持元数据提取

社区 MongoDB CDC 使用了 MongoDB 3.6推出的 Change Streams特性,通过将 Change Streams 转换成 Flink Upsert changelog,实现了 MongoDB CDC TableSource。在 MongoDB 6.0 之前的版本中,默认不会提供变更前文档及被删除文档的数据,利用这些信息只能实现下图所示的 Upsert 语义。

MongoDB 6.0 的 Pre- and Post-Image 新功能提供了一个更高效的解决方案:只要启用changeStreamPreAndPostImages功能,MongoDB 就会在每次变更发生时,在一个特殊的集合中记录文档变更前后的完整状态。MongoDB CDC 支持读取这些记录并产生完整事件流,从而消除了对 ChangelogNormalize 节点的依赖,该功能在社区和阿里云实时计算Flink产品中均可以支持。

三、MongoDB CDC 在阿里云 Flink 实时计算产品的实践

社区的 MongoDB CDC 作为纯引擎,功能已经十分强大。但作为商业化产品,目前仍然存在着不足之处,即无法支持 Schema 变更。

MongoDB 作为 NoSQL 数据库,没有固定的 Schema 要求,Schema 的变更操作十分常见,但目前社区 MongoDB CDC 只能支持固定 Schema,并且无法支持 Schema 变更。同时社区 MongoDB CDC 需要用户手动定义表的 Schema,在使用上也不够便捷。

为了解决上述不足之处,阿里云 Flink 实时计算产品提供了 MongoDB Catalog,支持 MongoDB 的 Schema 推导,无需手动定义 Schema。并且通过 CTAS/CDAS 语句,能够做到在实时同步 MongoDB 数据的同时将上游表结构(Schema)的变更同步到下游表,提高了建表和维护表结构变更的效率。

1.Schema 推导的实现

MongoDB Schema 推导通过 MongoDB Catalog 实现,MongoDB Catalog 会推导出 collection 的 schema,无需手动指定 DDL 即可作为 Flink 源表、维表或结果表使用。Schema 推导的流程包括以下步骤:

1.1 数据采样

MongoDB Catalog 会从 Collection 中采样默认 100 条文档数据,若 Collection 中文档数小于该值,则会获取其中的所有数据。

采样数据量可以通过 MongoDB Catalog 提供的配置项 max.fetch.records 进行设置。

1.2 Schema 解析

在 MongoDB 中,每个 Document 都是一个 BSON 文档。与 JSON 相比,BSON 类型是 JSON 类型的超集,相比 JSON 额外支持了 DateTime、Binary 等类型。在解析单个 BSON 文档的 Schema 时,BSON 类型会与 Flink SQL 类型进行一一对应。对于 BSON 文档中嵌套的 Document 类型,默认会将其解析为 STRING。

为了能够更好地解析嵌套的 Document 类型,MongoDB Catalog提供了 scan.flatten-nested-columns.enabled 配置项,可以用于递归地解析 Document 类型中的字段。假设初始的 BSON 文档如下:

{
  "unnested": "value",
  "nested": {
    "col1": 99,
    "col2": true
  }
}

如果将 scan.flatten-nested-columns.enabled 设为 false(默认),得到的 Schema 会包含 2 列:

列名 Flink SQL类型
unnested STRING
nested STRING

如果将 scan.flatten-nested-columns.enabled 设为 true,得到的 Schema 则会包含 3 列:

列名 Flink SQL类型
unnested STRING
nested.col1 INT
nested.col2 BOOLEAN

除此之外,MongoDB Catalog 还提供了 scan.primitive-as-string 配置项,可以将所有 BSON 基本类型都映射为 STRING。

1.3 Schema 合并

当获取到一组 BSON 文档数据后,MongoDB Catalog 会逐条解析 BSON 文档,并按如下规则合并解析出的物理列,最终得到的 Schema 会作为整个 Collection 的 Schema。合并规则如下:

  • 如果当前 BSON 文档解析出的物理列中包含结果 Schema 中没有的字段,则 MongoDB Catalog 会自动将这些字段加入到结果 Schema。

  • 如果当前 BSON 文档解析出的物理列和结果 Schema 出现了同名列,若类型不同,则会按下图的树形结构找到最近公共父节点,作为该同名列的类型。

例如,对于包含如下三条数据的 Collection:

{
  "_id": {
    "$oid": "100000000000000000000101"
  },
  "name": "Alice",
  "age": 10,
  "phone": {
    "mother": "111",
    "fatehr": "222"
  }
}

{
  "_id": {
    "$oid": "100000000000000000000102"
  },
  "name": "Bob",
  "age": 20,
  "phone": {
    "mother": "333",
    "fatehr": "444"
  }
  "address": ["Shanghai"],
  "desc": 1024
}

{
  "_id": {
    "$oid": "100000000000000000000103"
  },
  "name": "John",
  "age": 30,
  "phone": {
    "mother": "555",
    "fatehr": "666"
  }
  "address": ["Shanghai"],
  "desc": "test value"
}

对于以上 3 个 BSON 文档,后两个相比第一个多了 address 和 desc 字段,这两个字段在做 Schema 合并时会合并到最终 Schema 中。后两个文档的 desc 字段类型不同,在解析单个文档的 Schema 时,会将这两个字段分别映射为 Flink SQL 类型的 INT 和 STRING,根据上述 Schema 合并时类型合并规则,最终 desc 字段类型会被推导为 STRING。

因此,MongoDB Catalog 最终得到的 Schema 如下:

列名 Flink SQL类型 备注
_id STRING NOT NULL 主键字段
name STRING
age INT
phone STRING
address STRING
desc STRING 类型合并为STRING

在 MongoDB 中,每个文档都有一个特殊的字段 _id,它用于唯一标识集合(collection)中的一个文档,这个字段在文档创建时会自动生成。

MongoDB Catalog 会把 _id 列作为主键,添加默认的主键约束,确保数据不会重复。

2. Schema Evolution 的实现

在将 MongoDB Catalog 中的表作为 CDC source 使用时,考虑到 Collection 中的数据可能会出现新增字段、更改字段类型等 Schema 变更操作,connector 在处理数据时需要考虑到 Schema evolution。

MongoDB CDC connector 会将 MongoDB Catalog 推导出的 Schema 作为初始 Schema,后续在每读到一条 OpLog 操作日志数据时,操作步骤如下:

  1. 解析当前数据对应 BSON 文档的 Schema,步骤与上文 BSON 文档 Schema 解析中相同
  2. 将步骤 1 中解析出的 Schema 与当前 Schema 合并
  3. 比较步骤 2 中合并后的 Schema 与当前 Schema:
  • 若相同,则使用当前 Schema 解析数据
  • 若不同,则更新当前 Schema,并下发 Schema 变更信息

3. 通过 CTAS/CDAS 语句同步数据和表结构

CTAS 语句支持同步源表的全量和增量数据到结果表中,在同步数据的同时,能够将源表的表结构变更也实时同步到结果表。CDAS 语句支持整库级别的数据实时同步,也能够支持表结构变更的同步。

在使用 CTAS/CDAS 语句同步数据之前,需要先创建 MongoDB Catalog:

CREATE CATALOG <yourcatalogname> WITH(
  'type'='mongodb',
  'default-database'='<dbName>',
  'hosts'='<hosts>',
  'scheme'='<scheme>',
  'username'='<username>',
  'password'='<password>',
  'connection.options'='<connectionOptions>',
  'max.fetch.records'='100',
  'scan.flatten-nested-columns.enable'='<flattenNestedColumns>',
  'scan.primitive-as-string'='<primitiveAsString>'
);

示例如下:

在创建 MongoDB Catalog 后,可以选择如下几种方式实现数据和表结构的同步:

3.1 使用 CTAS 语句同步单个 MongoDB Collection 数据和表结构到下游存储

CREATE TABLE IF NOT EXISTS `${target_table_name}`
WITH(...)
AS TABLE `${mongodb_catalog}`.`${db_name}`.`${collection_name}`
/*+ OPTIONS('scan.incremental.snapshot.enabled'='true') */;

示例如下:

3.2 使用多个 CTAS 语句同时同步多个 MongoDB Collection 数据和表结构到下游存储

BEGIN STATEMENT SET;

CREATE TABLE IF NOT EXISTS `some_catalog`.`some_database`.`some_table0`
AS TABLE `mongodb-catalog`.`database`.`collection0`
/*+ OPTIONS('scan.incremental.snapshot.enabled'='true') */;

CREATE TABLE IF NOT EXISTS `some_catalog`.`some_database`.`some_table1`
AS TABLE `mongodb-catalog`.`database`.`collection1`
/*+ OPTIONS('scan.incremental.snapshot.enabled'='true') */;

CREATE TABLE IF NOT EXISTS `some_catalog`.`some_database`.`some_table2`
AS TABLE `mongodb-catalog`.`database`.`collection2`
/*+ OPTIONS('scan.incremental.snapshot.enabled'='true') */;

END;

示例如下:

3.3 使用 CDAS 同步 MongoDB 数据库中符合条件的 Collection 数据和表结构到下游存储

CREATE DATABASE IF NOT EXISTS `some_catalog`.`some_database` 
AS DATABASE `mongo-catalog`.`database` INCLUDING TABLE 'table-name'
/*+ OPTIONS('scan.incremental.snapshot.enabled'='true') */;

示例如下:

4. 使用示例

(以下示例使用的环境为阿里云实时计算 Flink 版

假设我们需要同步 MongoDB 中单个数据库下所有 Collection 的数据和表结构到 Hologres,MongoDB 中数据可能出现新增字段。

MongoDB 的数据库名称为 guiyuan_cdas_test,其中包含了两个 collection,名称分别为 test_coll_0 和 test_coll_1,我们希望将数据同步到 Hologres 的同名数据库 cdas_test 中。

MongoDB 中两个 collection 的初始数据如下:

创建 MongoDB 和 Hologres 的 Catalog 后,在 SQL 开发页面编写 CDAS 作业,由于 MongoDB Catalog 会对 collection 做 Schema 推导,此处不需要手动定义表的 DDL:

部署运行后,可以看到 Hologres 数据库中已经自动创建了 guiyuan_cdas_test 数据库,并且同步了两个表的初始数据:

此时,向 MongoDB 的 test_coll_0 中插入一条包含了新字段 address 的数据,同时向 test_coll_1 中插入一条包含了新字段 phone 的数据。

此时观察 Hologres 表,可以看到两个表都已经同步了新的数据和表结构:

四. 总结

Flink CDC 基于 MongoDB 的 Change Streams 实现了 MongoDB CDC Source,支持了 MongoDB 的全增量一体化数据同步。在此基础上,阿里云实时计算 Flink 通过 MongoDB Catalog 实现了 MongoDB Schema 推导,配合 CTAS/CDAS 语句,可以在同步数据的同时支持表结构变更的同步,当 Schema 发生变更时,无需修改 Flink 作业即可同步到下游存储,极大地提升了数据集成的灵活性和便利性。


Flink Forward Asia 2023

本届 Flink Forward Asia 更多精彩内容,可微信扫描图片二维码观看全部议题的视频回放及 FFA 2023 峰会资料!


更多内容

img


活动推荐

阿里云基于 Apache Flink 构建的企业级产品-实时计算 Flink 版现开启活动:
0 元试用 实时计算 Flink 版(5000CU*小时,3 个月内)
了解活动详情:https://free.aliyun.com/?pipCode=sc

image.png

相关实践学习
基于Hologres+Flink搭建GitHub实时数据大屏
通过使用Flink、Hologres构建实时数仓,并通过Hologres对接BI分析工具(以DataV为例),实现海量数据实时分析.
实时计算 Flink 实战课程
如何使用实时计算 Flink 搞定数据处理难题?实时计算 Flink 极客训练营产品、技术专家齐上阵,从开源 Flink功能介绍到实时计算 Flink 优势详解,现场实操,5天即可上手! 欢迎开通实时计算 Flink 版: https://cn.aliyun.com/product/bigdata/sc Flink Forward Asia 介绍: Flink Forward 是由 Apache 官方授权,Apache Flink Community China 支持的会议,通过参会不仅可以了解到 Flink 社区的最新动态和发展计划,还可以了解到国内外一线大厂围绕 Flink 生态的生产实践经验,是 Flink 开发者和使用者不可错过的盛会。 去年经过品牌升级后的 Flink Forward Asia 吸引了超过2000人线下参与,一举成为国内最大的 Apache 顶级项目会议。结合2020年的特殊情况,Flink Forward Asia 2020 将在12月26日以线上峰会的形式与大家见面。
相关文章
|
分布式计算 数据处理 Apache
Spark和Flink的区别是什么?如何选择?都应用在哪些行业?
【10月更文挑战第10天】Spark和Flink的区别是什么?如何选择?都应用在哪些行业?
1432 1
|
8月前
|
存储 NoSQL 物联网
MongoDB应用场景
MongoDB应用场景
|
8月前
|
存储 运维 监控
阿里妈妈基于 Flink+Paimon 的 Lakehouse 应用实践
本文总结了阿里妈妈数据技术专家陈亮在Flink Forward Asia 2024大会上的分享,围绕广告业务背景、架构设计及湖仓方案演进展开。内容涵盖广告生态运作、实时数仓挑战与优化,以及基于Paimon的湖仓方案优势。通过分层设计与技术优化,实现业务交付周期缩短30%以上,资源开销降低40%,并大幅提升系统稳定性和运营效率。文章还介绍了阿里云实时计算Flink版的免费试用活动,助力企业探索实时计算与湖仓一体化解决方案。
942 3
阿里妈妈基于 Flink+Paimon 的 Lakehouse 应用实践
|
8月前
|
SQL 弹性计算 DataWorks
Flink CDC 在阿里云 DataWorks 数据集成入湖场景的应用实践
Flink CDC 在阿里云 DataWorks 数据集成入湖场景的应用实践
397 6
|
8月前
|
存储 NoSQL 关系型数据库
微服务——MongoDB的应用场景
随着Web2.0时代的到来,传统关系型数据库(如MySQL)在高并发读写、海量数据存储及高可扩展性需求方面逐渐力不从心。而MongoDB凭借其灵活的文档结构和高效性能,在社交、游戏、物流、物联网和视频直播等场景中表现出色。这些场景通常具有数据量大、写入频繁且对事务要求不高的特点。选择MongoDB适合以下情况:应用无需复杂事务与join支持、需求不确定需快速迭代、需处理高QPS读写或超大规模数据存储、追求高可用性和快速水平扩展能力。相比MySQL,MongoDB能以更低的学习、开发和运维成本满足现代应用需求。
283 0
|
11月前
|
消息中间件 JSON 数据库
探索Flink动态CEP:杭州银行的实战案例
本文由杭州银行大数据工程师唐占峰、欧阳武林撰写,介绍Flink动态CEP的定义、应用场景、技术实现及使用方式。Flink动态CEP是基于Flink的复杂事件处理库,支持在不重启服务的情况下动态更新规则,适应快速变化的业务需求。文章详细阐述了其在反洗钱、反欺诈和实时营销等金融领域的应用,并展示了某金融机构的实际应用案例。通过动态CEP,用户可以实时调整规则,提高系统的灵活性和响应速度,降低维护成本。文中还提供了具体的代码示例和技术细节,帮助读者理解和使用Flink动态CEP。
1366 2
探索Flink动态CEP:杭州银行的实战案例
|
11月前
|
存储 NoSQL atlas
探索MongoDB:发展历程、优势与应用场景
MongoDB 是一个开源的文档型数据库,由 DoubleClick 团队于2007年创立,旨在解决传统数据库的扩展性和灵活性问题。它支持 JSON 格式的存储和查询,具备高可用性、高扩展性和灵活性等优势。MongoDB 适用于社交、物联网、视频直播和内容管理等多种场景,并被阿里巴巴、腾讯等一线互联网公司广泛使用。其主要版本包括 MongoDB Atlas(云服务)、MongoDB Enterprise Advanced(商业版)和 MongoDB Community Edition(免费版)。自2009年发布1.0版本以来,MongoDB 不断创新,最新版本为7.0,在性能和功能上持续优化。
743 12
|
JavaScript NoSQL 前端开发
使用 Node.js 和 MongoDB 构建实时聊天应用
【10月更文挑战第2天】使用 Node.js 和 MongoDB 构建实时聊天应用
|
4月前
|
NoSQL MongoDB 数据库
数据库数据恢复—MongoDB数据库数据恢复案例
MongoDB数据库数据恢复环境: 一台操作系统为Windows Server的虚拟机上部署MongoDB数据库。 MongoDB数据库故障: 工作人员在MongoDB服务仍然开启的情况下将MongoDB数据库文件拷贝到其他分区,数据复制完成后将MongoDB数据库原先所在的分区进行了格式化操作。 结果发现拷贝过去的数据无法使用。管理员又将数据拷贝回原始分区,MongoDB服务仍然无法使用,报错“Windows无法启动MongoDB服务(位于 本地计算机 上)错误1067:进程意外终止。”
|
4月前
|
缓存 NoSQL Linux
在CentOS 7系统中彻底移除MongoDB数据库的步骤
以上步骤完成后,MongoDB应该会从您的CentOS 7系统中被彻底移除。在执行上述操作前,请确保已经备份好所有重要数据以防丢失。这些步骤操作需要一些基本的Linux系统管理知识,若您对某一步骤不是非常清楚,请先进行必要的学习或咨询专业人士。在执行系统级操作时,推荐在实施前创建系统快照或备份,以便在出现问题时能够恢复到原先的状态。
406 79

相关产品

  • 实时计算 Flink版
  • 推荐镜像

    更多