-
Notifications
You must be signed in to change notification settings - Fork 1.2k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
cdc: make mq encoding protocol related more clear (#18783)
- Loading branch information
1 parent
12d4367
commit 4543d9b
Showing
2 changed files
with
63 additions
and
37 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -5,52 +5,35 @@ summary: 了解 TiCDC Avro Protocol 的概念和使用方法。 | |
|
||
# TiCDC Avro Protocol | ||
|
||
Avro 是由 [Apache Avro™](https://avro.apache.org/) 定义的一种数据交换格式协议,[Confluent Platform](https://docs.confluent.io/platform/current/platform.html) 选择它作为默认的数据交换格式。通过本文,你可以了解 TiCDC 对 Avro 数据格式的实现,包括 TiDB 扩展字段、Avro 数据格式定义,以及和 [Confluent Schema Registry](https://docs.confluent.io/platform/current/schema-registry/index.html) 的交互。 | ||
TiCDC Avro 协议,是对 [Confluent Platform](https://docs.confluent.io/platform/current/platform.html) 定义的 [Confluent Avro](https://docs.confluent.io/platform/current/schema-registry/fundamentals/serdes-develop/serdes-avro.html) 数据传输格式的第三方实现。Avro 是由 [Apache Avro™](https://avro.apache.org/) 定义的一种数据交换格式。 | ||
|
||
通过本文,你可以了解 TiCDC Avro 数据协议的实现,以及和 [Confluent Schema Registry](https://docs.confluent.io/platform/current/schema-registry/index.html) 的交互。 | ||
|
||
> **警告:** | ||
> | ||
> 从 v7.3.0 起,如果开启了[同步没有有效索引的表](/ticdc/ticdc-manage-changefeed.md#同步没有有效索引的表),创建使用 Avro 协议的 changefeed 时会报错。 | ||
## 使用 Avro | ||
|
||
当使用 Message Queue (MQ) 作为下游 Sink 时,你可以在 `sink-uri` 中指定使用 Avro。TiCDC 获取 TiDB 的 DML 事件,并将这些事件封装到 Avro Message,然后发送到下游。当 Avro 检测到 schema 变化时,会向 Schema Registry 注册最新的 schema。 | ||
|
||
使用 Avro 时的配置样例如下所示: | ||
|
||
```shell | ||
cdc cli changefeed create --server=http://127.0.0.1:8300 --changefeed-id="kafka-avro" --sink-uri="kafka://127.0.0.1:9092/topic-name?protocol=avro" --schema-registry=http://127.0.0.1:8081 --config changefeed_config.toml | ||
``` | ||
|
||
`--schema-registry` 的值支持 `https` 协议和 `username:password` 认证,username 和 password 必须经过 URL 编码。例如,`--schema-registry=https://username:[email protected]`。 | ||
|
||
> **注意:** | ||
> | ||
> 使用 Avro 协议时,一个 Kafka Topic 只能包含一张表的数据。你需要在配置文件中配置 [Topic 分发器](/ticdc/ticdc-sink-to-kafka.md#topic-分发器)。 | ||
```shell | ||
[sink] | ||
dispatchers = [ | ||
{matcher = ['*.*'], topic = "tidb_{schema}_{table}"}, | ||
] | ||
``` | ||
|
||
`--schema-registry` 的值支持 https 协议和 username:password 认证,比如`--schema-registry=https://username:[email protected]`,username 和 password 必须经过 URL 编码。 | ||
|
||
## TiDB 扩展字段 | ||
|
||
默认情况下,Avro 只收集在 DML 事件中发生数据变更的行的所有数据信息,不收集数据变更的类型和 TiDB 专有的 CommitTS 事务唯一标识信息。为了解决这个问题,TiCDC 在 Avro 协议格式中附加了 TiDB 扩展字段。当 `sink-uri` 中设置 `enable-tidb-extension` 为 `true` (默认为 `false`)后,TiCDC 生成 Avro 消息时会新增三个字段: | ||
|
||
- `_tidb_op`:DML 的类型,"c" 表示插入,"u" 表示更新。 | ||
- `_tidb_commit_ts`:事务唯一标识信息。 | ||
- `_tidb_commit_physical_time`:事务标识信息中现实时间的时间戳。 | ||
|
||
配置样例如下所示: | ||
|
||
```shell | ||
cdc cli changefeed create --server=http://127.0.0.1:8300 --changefeed-id="kafka-avro-enable-extension" --sink-uri="kafka://127.0.0.1:9092/topic-name?protocol=avro&enable-tidb-extension=true" --schema-registry=http://127.0.0.1:8081 --config changefeed_config.toml | ||
``` | ||
|
||
```shell | ||
[sink] | ||
dispatchers = [ | ||
{matcher = ['*.*'], topic = "tidb_{schema}_{table}"}, | ||
] | ||
``` | ||
|
||
## 数据格式定义 | ||
|
||
TiCDC 会将一个 DML 事件转换为一个 kafka 事件,其中事件的 key 和 value 都按照 Avro 协议进行编码。 | ||
|
@@ -89,7 +72,36 @@ Key 中的 `fields` 只包含主键或唯一索引列。 | |
} | ||
``` | ||
|
||
Value 数据格式默认与 Key 数据格式相同,但是 Value 的 `fields` 中包含了所有的列,而不仅仅是主键列。 | ||
Value 数据格式默认与 Key 数据格式相同,但是 Value 的 `fields` 中包含了所有的列。 | ||
|
||
> **注意:** | ||
> | ||
> Avro 协议在编码 DML 事件时,操作方式如下: | ||
> | ||
> - 对于 Delete 事件,只编码 Key 部分,Value 部分为空。 | ||
> - 对于 Insert 事件,编码所有列数据到 Value 部分。 | ||
> - 对于 Update 事件,只编码更新后的所有列数据到 Value 部分。 | ||
## TiDB 扩展字段 | ||
|
||
默认情况下,Avro 只编码在 DML 事件中发生数据变更的行的所有列数据信息,不收集数据变更的类型和 TiDB 专有的 CommitTS 事务唯一标识信息。为了解决这个问题,TiCDC 在 Avro 协议格式中附加了 TiDB 扩展字段。当 `sink-uri` 中设置 `enable-tidb-extension` 为 `true` (默认为 `false`)后,TiCDC 生成 Avro 消息时,会在 Value 部分新增三个字段: | ||
|
||
- `_tidb_op`:DML 的类型,"c" 表示插入,"u" 表示更新。 | ||
- `_tidb_commit_ts`:事务唯一标识信息。 | ||
- `_tidb_commit_physical_time`:事务标识信息中现实时间的时间戳。 | ||
|
||
配置样例如下所示: | ||
|
||
```shell | ||
cdc cli changefeed create --server=http://127.0.0.1:8300 --changefeed-id="kafka-avro-enable-extension" --sink-uri="kafka://127.0.0.1:9092/topic-name?protocol=avro&enable-tidb-extension=true" --schema-registry=http://127.0.0.1:8081 --config changefeed_config.toml | ||
``` | ||
|
||
```shell | ||
[sink] | ||
dispatchers = [ | ||
{matcher = ['*.*'], topic = "tidb_{schema}_{table}"}, | ||
] | ||
``` | ||
|
||
如果开启了 [TiDB 扩展字段](#tidb-扩展字段),那么 Value 数据格式将会变成: | ||
|
||
|
@@ -155,7 +167,7 @@ Column 数据格式即 Key/Value 数据格式中的 `{{ColumnValueBlock}}` 部 | |
|
||
- `{{ColumnName}}` 表示列名。 | ||
- `{{TIDB_TYPE}}` 表示对应到 TiDB 中的类型,与原始的 SQL Type 不是一一对应关系。 | ||
- `{{AVRO_TYPE}}` 表示 [avro spec](https://avro.apache.org/docs/current/spec.html) 中的类型。 | ||
- `{{AVRO_TYPE}}` 表示 [Avro Specification](https://avro.apache.org/docs/++version++/specification) 中的类型。 | ||
|
||
| SQL TYPE | TIDB_TYPE | AVRO_TYPE | 说明 | | ||
|------------|-----------|-----------|---------------------------------------------------------------------------------------------------------------------------| | ||
|
@@ -266,14 +278,27 @@ DECIMAL(10, 4) | |
|
||
## DDL 事件与 Schema 变更 | ||
|
||
Avro 并不会向下游生成 DDL 事件。Avro 会在每次 DML 事件发生时检测是否发生 schema 变更,如果发生了 schema 变更,Avro 会生成新的 schema,并尝试向 Schema Registry 注册。注册时,Schema Registry 会做兼容性检测,如果此次 schema 变更没有通过兼容性检测,注册将会失败,TiCDC 并不会尝试解决 schema 的兼容性问题。 | ||
Avro 协议并不会向下游发送 DDL 事件和 Watermark 事件。Avro 会在每次 DML 事件发生时检测是否发生 schema 变更,如果发生了 schema 变更,Avro 会生成新的 schema,并尝试向 Schema Registry 注册。注册时,Schema Registry 会做兼容性检测,如果此次 schema 变更没有通过兼容性检测,注册将会失败,TiCDC 并不会尝试解决 schema 的兼容性问题。 | ||
|
||
同时,即使 schema 变更通过兼容性检测并成功注册新版本,数据的生产者和消费者可能仍然需要升级才能正确工作。 | ||
比如,Confluent Schema Registry 默认的[兼容性策略](https://docs.confluent.io/platform/current/schema-registry/fundamentals/schema-evolution.html#compatibility-types)是 `BACKWARD`,在这种策略下,如果你在源表增加一个非空列,Avro 在生成新 schema 向 Schema Registry 注册时将会因为兼容性问题失败,这个时候 changefeed 将会进入 error 状态。 | ||
|
||
比如,Confluent Schema Registry 默认的兼容性策略是 BACKWARD,在这种策略下,如果你在源表增加一个非空列,Avro 在生成新 schema 向 Schema Registry 注册时将会因为兼容性问题失败,这个时候 changefeed 将会进入 error 状态。 | ||
同时,即使 schema 变更通过兼容性检测并成功注册新版本,数据的生产者和消费者可能仍然需要获取到新版本的 schema,才能对数据进行正确编解码。 | ||
|
||
如需了解更多 schema 相关信息,请参阅 [Schema Registry 的相关文档](https://docs.confluent.io/platform/current/schema-registry/avro.html)。 | ||
|
||
## 消费者实现 | ||
|
||
TiCDC Avro 协议支持被 [`io.confluent.kafka.serializers.KafkaAvroDeserializer`](https://docs.confluent.io/platform/current/schema-registry/fundamentals/serdes-develop/serdes-avro.html#avro-deserializer) 反序列化。 | ||
|
||
消费者程序可以通过 [Schema Registry API](https://docs.confluent.io/platform/current/schema-registry/develop/api.html) 获取到最新的 schema,然后对数据进行反序列化。 | ||
|
||
### 区分事件类型 | ||
|
||
消费者程序可以按照如下规则区分 DML 事件类型: | ||
|
||
* 只有 Key 部分,则是 Delete 事件。 | ||
* 含有 Value 部分,则是 Insert 或 Update 事件。如果用户开启了 [TiDB 扩展字段功能](#tidb-扩展字段),可以根据其中的 `_tidb_op` 字段,判断该条事件变更是 Insert 或 Update。如果未开启 TiDB 扩展字段功能,则无法区分。 | ||
|
||
## Topic 分发 | ||
|
||
Schema Registry 支持三种 [Subject Name Strategy](https://docs.confluent.io/platform/current/schema-registry/serdes-develop/index.html#subject-name-strategy):TopicNameStrategy、RecordNameStrategy 和 TopicRecordNameStrategy。目前 TiCDC Avro 只支持 TopicNameStrategy 一种,这意味着一个 kafka topic 只能接收一种数据格式的数据,所以 TiCDC Avro 禁止将多张表映射到同一个 topic。在创建 changefeed 时,如果配置的分发规则中,topic 规则不包含 `{schema}` 和 `{table}` 占位符,将会报错。 | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters