我很荣幸地宣布 Debezium 1.8 系列的第一个版本,1.8.0.Alpha1

随着秋天的色彩渐浓,团队一直在努力为这个版本编写代码。Debezium 1.8.0.Alpha1 带来了许多改进,但最值得注意的是对原生 MongoDB 4.0 变更流的支持!

MongoDB Change Streams 支持

MongoDB 的 change streams (更改流) 允许应用程序或客户端访问实时更改数据捕获事件,而无需复杂地跟踪 oplog。此功能最初由 MongoDB 引擎在 3.6 版本中引入;然而,该功能受到限制。从 MongoDB 4.0 开始,更改流现在可以捕获跨数据库、副本集甚至分片集群的更改。

Debezium 为其添加了更改流支持

  • 实现与 MongoDB 5 的兼容性(尚未测试,请参阅下面的未来工作)。

  • 在更新事件中提供完整的文档输出(见下文)。

  • 从内部(且可能不断变化)的 oplog 格式细节中抽象出来,使这个新实现未来有可能取代 oplog 读取。

要使用 Debezium 的更改流支持,您必须使用 MongoDB 4.0 或更高版本。

启用

Debezium for MongoDB 公开了一个名为 capture.mode 的新配置属性。捕获模式指定连接器应如何从 MongoDB 数据库获取更改事件。有效选项是:

oplog

指定应通过跟踪 oplog 来捕获更改;这是旧的行为。

change_streams

指定应通过使用 MongoDB 更改流来捕获更改。更新将不包含完整的消息;事件中只包含已更改的字段。

change_streams_update_full

指定应通过使用 MongoDB 更改流来捕获更改。更新将包含事件中当前记录的完整快照。这是连接器的新默认设置。

新的 change_streamschange_streams_update_full 捕获模式尚处于孵化阶段,其格式和工作细节在未来的版本中可能会发生变化。

事件变化

使用我们 示例仓库 中的教程,让我们来看看这些捕获模式的区别。

首先,让我们向 customers 集合添加一条新记录。使用 MongoDB shell,可以通过运行以下命令来完成:

db.customers.insert([
    {
        _id : NumberLong("1005"),
        first_name : 'Bob',
        last_name : 'Hopper',
        email : 'thebob@example.com',
        unique_id : UUID() }
]);

这将生成一个更改事件,但您会发现,如果检查 topic,本版本中事件的内容并没有太大不同。由于该事件是插入操作,因此所有字段值都包含在发出的事件中。

在更新时,这就是我们可以看到捕获模式差异发挥作用的地方。现在使用 MongoDB shell 和以下命令修改客户的名字和姓氏:

db.customers.update(
    { _id:NumberLong("1005") },
    { $set: {
        first_name: "Bobby",
        last_name: "Copper"
    } });

这会修改 ID 为 1005 的客户的名字和姓氏。以下部分显示了给定捕获模式的每个事件的外观。

Oplog

以下显示了在使用 oplog 捕获模式时更新事件的片段。

{
  "schema": {
      ...
  },
  "payload": {
    "after": null,
    "patch": "{\"$v\": 1, \"$set\": { \"first_name\": \"Bobby\", \"last_name\": \"Copper\"}}",
    "filter": "{\"_id\": {\"$numberLong\": \"1005\"}}",
    "updateDescription": null,
    "source": {
      "version": "1.8.0.Alpha1",
      "connector": "mongodb",
      "name": "dbserver1",
      "ts_ms": 1635291250000,
      "snapshot": "false",
      "db": "inventory",
      "sequence": null,
      "rs": "rs0",
      "collection": "customers",
      "ord": 1,
      "h": 3510217852938498600,
      "tord": null,
      "stxnid": null
    },
    "op": "u",
    "ts_ms": 1635291250803,
    "transaction": null
  }
}

发出的事件的 after 字段没有值。相反,事件提供了 patchfilter 的值,这些值描述了源文档中已更改内容的有限细节。由于事件仅提供有关哪些字段已更改的信息,而不提供未更改字段的值,因此这可能不适合需要了解完整文档的某些消费者。

Change Streams

以下显示了在使用 change_streams 捕获模式时更新事件的片段。

{
  "schema": {
      ...
  },
  "payload": {
    "after": null,
    "patch": null,
    "filter": null,
    "updateDescription": {
      "removedFields": null,
      "updatedFields": "{\"first_name\": \"Bobby\", \"last_name\": \"Copper\"}",
      "truncatedArrays": null
    },
    "source": {
      "version": "1.8.0.Alpha1",
      "connector": "mongodb",
      "name": "dbserver1",
      "ts_ms": 1635292448000,
      "snapshot": "false",
      "db": "inventory",
      "sequence": null,
      "rs": "rs0",
      "collection": "customers",
      "ord": 1,
      "h": null,
      "tord": null,
      "stxnid": null
    },
    "op": "u",
    "ts_ms": 1635292448736,
    "transaction": null
  }
}

发出的事件具有与旧版 oplog 输出略有不同的值集。如上所示,事件在 afterpatchfilter 字段中没有值。取而代之的是,事件依赖于在 updateDescription 结构中描述文档字段的更改。虽然这提供了关于由于更新而可能已设置甚至已取消设置的值的更多详细信息,但对于需要源文档所有字段值的某些消费者来说,这可能仍然不是理想的。

Change Streams Full Document

以下显示了在使用 change_streams_update_full 捕获模式时更新事件的片段。

{
  "schema": {
      ...
  },
  "payload": {
    "after": "{\"_id\": {\"$numberLong\": \"1005\"},\"first_name\": \"Bobby\",\"last_name\": \"Copper\",\"email\": \"thebob@example.com\",\"unique_id\": {\"$binary\": \"KRywzYp5RneNu8DUmhQHAQ==\",\"$type\": \"04\"}}",
    "patch": null,
    "filter": null,
    "updateDescription": {
      "removedFields": null,
      "updatedFields": "{\"first_name\": \"Bobby\", \"last_name\": \"Copper\"}",
      "truncatedArrays": null
    },
    "source": {
      "version": "1.8.0.Alpha1",
      "connector": "mongodb",
      "name": "dbserver1",
      "ts_ms": 1635292878000,
      "snapshot": "false",
      "db": "inventory",
      "sequence": null,
      "rs": "rs0",
      "collection": "customers",
      "ord": 1,
      "h": null,
      "tord": null,
      "stxnid": null
    },
    "op": "u",
    "ts_ms": 1635292878244,
    "transaction": null
  }
}

此捕获模式与 change_streams 模式几乎相同,只有一个关键区别:after 字段填充了文档的完整快照。此模式非常适合依赖源文档中所有字段的消费者。

有关完整文档模式语义的更多详细信息,请参阅 MongoDB 文档

完整文档模式基于 MongoDB 通过更改流向连接器提供更改事件时对源文档的重新选择。在同一文档发生多次更改且时间间隔很近的情况下,每个事件都可能具有相同的完整文档表示。

未来工作

结合已经完成的 MongoDB 更改流工作,我们认识到还有很多工作要做,包括针对 MongoDB 5 测试新的更改流实现,以及更新连接器文档以反映这些新变化。您可以期待在下一个预览版本中提供这些以及更多内容。根据更新的 Debezium 1.8 路线图,我们还计划为 Debezium 的 MongoDB 连接器添加增量快照支持,以及一个支持此连接器事件格式的 outbox 事件路由器变体。

其他修复

此版本中修复了许多错误并进行了稳定性改进,其中一些值得注意的包括:

  • LogMiner 查询中的行哈希无法区分语句行(DBZ-3834

  • 增量快照中组合主键的 chunk select 语句不正确(DBZ-3860

  • column.the mask.hash.hashAlgorithm.with…​ 使用此功能时发生数据损坏(DBZ-4033

  • 配置了同一 Oracle 数据库的多个连接器时,Infinispan SPI 会抛出 NPE(DBZ-4064

展望

随着年底临近,我们将以同样的精力继续前进。我们已经在邮件列表中就 Debezium 2.0 启动了 公开讨论。您的反馈非常宝贵,请告诉我们您希望添加、更改或改进的内容!与此同时,您还可以期待在下周发布 Debezium 1.7 系列的次要错误修复版本,以及在几周后发布 Debezium 1.8 系列的另一个预览版本。祝您流式传输愉快!

Chris Cranford

Chris 是 IBM 的一名软件工程师,之前在 Red Hat 工作,他致力于 Debezium 项目,并每天都在深入研究 Oracle 和 Change Data Capture 的各个方面。他此前曾从事 Hibernate(领先的开源 JPA 持久化框架)方面的工作,并且继续为 Quarkus 做贡献。Chris 居住在美国北卡罗来纳州。

   


关于 Debezium

Debezium 是一个开源的分布式平台,可以将现有数据库转变为事件流,使应用程序能够几乎即时地看到并响应数据库中已提交的每个行级更改。Debezium 构建在 Kafka 之上,并提供了 Kafka Connect 兼容的连接器,用于监控特定的数据库管理系统。Debezium 将数据更改的历史记录在 Kafka 日志中,这样您的应用程序可以随时停止和重新启动,并可以轻松地消费在未运行时错过的所有事件,确保所有事件都被正确且完整地处理。Debezium 在 Apache 许可证 2.0 下是 开源 的。

参与进来

我们希望您觉得 Debezium 有趣且有用,并希望尝试一下。在 Twitter @debezium 上关注我们,在 Zulip 上与我们聊天,或加入我们的 邮件列表 与社区交流。所有代码都在 GitHub 上开源,因此请在本地构建代码,帮助我们改进现有连接器并添加更多连接器。如果您发现问题或有改进 Debezium 的想法,请告诉我们或 记录一个问题

版权所有 © Debezium 及其作者。保留所有权利。有关我们的商标详情,请访问我们的 商标政策商标列表。第三方商标属于其各自所有者,在此提及并不表示任何认可或关联。
×