-
Notifications
You must be signed in to change notification settings - Fork 718
Add debezium avro protocol intro. #23270
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: release-8.5
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| @@ -0,0 +1,241 @@ | ||||||||||||||||||||||||||||||
| # TiCDC Debezium Avro Protocol | ||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||
| TiCDC Debezium Avro protocol combines Debezium-style change event semantics with Confluent Avro wire format. | ||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||
| In this protocol, TiCDC still produces Debezium envelope fields such as `before`, `after`, `source`, `op`, and `ts_ms`, but message bytes are encoded in Avro binary and schema ids are managed by Schema Registry. | ||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||
| Compared with `protocol=debezium`, `protocol=debezium-avro` is better suited for downstream systems that already use Avro deserializers and Schema Registry. | ||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||
| ## Use Debezium Avro | ||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||
| When you use Kafka as the downstream sink, specify `protocol=debezium-avro` in `sink-uri`, and provide the Schema Registry endpoint. | ||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||
| The configuration example is as follows: | ||||||||||||||||||||||||||||||
|
Comment on lines
+11
to
+13
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Let's improve the clarity and flow by adding appropriate articles and using active phrasing.
Suggested change
References
|
||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||
| ```shell | ||||||||||||||||||||||||||||||
| cdc cli changefeed create \ | ||||||||||||||||||||||||||||||
| --server=http://127.0.0.1:8300 \ | ||||||||||||||||||||||||||||||
| --changefeed-id="kafka-debezium-avro" \ | ||||||||||||||||||||||||||||||
| --sink-uri="kafka://127.0.0.1:9092/topic-name?protocol=debezium-avro&avro-decimal-handling-mode=precise&avro-bigint-unsigned-handling-mode=string" \ | ||||||||||||||||||||||||||||||
| --schema-registry=http://127.0.0.1:8081 \ | ||||||||||||||||||||||||||||||
| --config changefeed_config.toml | ||||||||||||||||||||||||||||||
| ``` | ||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||
| The value of `--schema-registry` supports the `https` protocol and `username:password` authentication. The username and password must be URL-encoded. For example, `--schema-registry=https://username:password@schema-registry-uri.com`. | ||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||
| > **Note:** | ||||||||||||||||||||||||||||||
| > | ||||||||||||||||||||||||||||||
| > Debezium Avro uses Schema Registry topic-name subject behavior. One Kafka topic should contain data for only one table. You need to configure topic dispatchers to route each table to an independent topic. | ||||||||||||||||||||||||||||||
|
Comment on lines
+26
to
+28
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. To maintain consistency with other documentation files (such as
Suggested change
References
|
||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||
| ```toml | ||||||||||||||||||||||||||||||
| [sink] | ||||||||||||||||||||||||||||||
| dispatchers = [ | ||||||||||||||||||||||||||||||
| {matcher = ['*.*'], topic = "tidb_{schema}_{table}"}, | ||||||||||||||||||||||||||||||
| ] | ||||||||||||||||||||||||||||||
| ``` | ||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||
| ## Definition of the data format | ||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||
| TiCDC converts a DML event into a Kafka event. The key and value are encoded as Debezium-model payloads over Avro wire format. | ||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||
| ### Wire format | ||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||
| Each Kafka message is encoded as: | ||||||||||||||||||||||||||||||
|
Comment on lines
+39
to
+43
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Let's rewrite this section to use active voice and improve readability.
Suggested change
References
|
||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||
| ```text | ||||||||||||||||||||||||||||||
| [magic byte][schema id][avro binary payload] | ||||||||||||||||||||||||||||||
| ``` | ||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||
| ### Key data format | ||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||
| The key contains only primary key columns or unique index columns. | ||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||
| The following JSON is the Debezium Connect schema model used before Avro binary encoding. | ||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||
| ```json | ||||||||||||||||||||||||||||||
| { | ||||||||||||||||||||||||||||||
| "schema": { | ||||||||||||||||||||||||||||||
| "type": "struct", | ||||||||||||||||||||||||||||||
| "optional": false, | ||||||||||||||||||||||||||||||
| "name": "{{ClusterID}}.{{SchemaName}}.{{TableName}}Key", | ||||||||||||||||||||||||||||||
| "fields": [ | ||||||||||||||||||||||||||||||
| { | ||||||||||||||||||||||||||||||
| "field": "id", | ||||||||||||||||||||||||||||||
| "type": "int64", | ||||||||||||||||||||||||||||||
| "optional": false | ||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||
| ] | ||||||||||||||||||||||||||||||
| }, | ||||||||||||||||||||||||||||||
| "payload": { | ||||||||||||||||||||||||||||||
| "id": 1 | ||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||
| ``` | ||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||
| #### Avro record naming (key) | ||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||
| When TiCDC converts this key schema to Avro and registers it in Schema Registry: | ||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||
| - `connect.name` keeps the full logical name: `{{ClusterID}}.{{SchemaName}}.{{TableName}}Key` | ||||||||||||||||||||||||||||||
| - Avro `name` becomes: `{{TableName}}Key` | ||||||||||||||||||||||||||||||
| - Avro `namespace` becomes: `{{ClusterID}}.{{SchemaName}}` | ||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||
| All parts are sanitized to Avro-compatible identifiers. | ||||||||||||||||||||||||||||||
|
Comment on lines
+77
to
+83
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Let's use active voice and add appropriate articles to improve the clarity of the record naming rules.
Suggested change
References
|
||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||
| ### Value data format | ||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||
| The value is a Debezium envelope and includes `before`, `after`, `source`, `op`, and `ts_ms`. | ||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||
| The following JSON is the Debezium Connect schema model used before Avro binary encoding. | ||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||
| ```json | ||||||||||||||||||||||||||||||
| { | ||||||||||||||||||||||||||||||
| "schema": { | ||||||||||||||||||||||||||||||
| "type": "struct", | ||||||||||||||||||||||||||||||
| "optional": false, | ||||||||||||||||||||||||||||||
| "name": "{{ClusterID}}.{{SchemaName}}.{{TableName}}Envelope", | ||||||||||||||||||||||||||||||
| "version": 1, | ||||||||||||||||||||||||||||||
| "fields": [ | ||||||||||||||||||||||||||||||
| { | ||||||||||||||||||||||||||||||
| "field": "before", | ||||||||||||||||||||||||||||||
| "type": "struct", | ||||||||||||||||||||||||||||||
| "optional": true, | ||||||||||||||||||||||||||||||
| "name": "{{ClusterID}}.{{SchemaName}}.{{TableName}}Value", | ||||||||||||||||||||||||||||||
| "fields": [ | ||||||||||||||||||||||||||||||
| {{RowFields}} | ||||||||||||||||||||||||||||||
| ] | ||||||||||||||||||||||||||||||
| }, | ||||||||||||||||||||||||||||||
| { | ||||||||||||||||||||||||||||||
| "field": "after", | ||||||||||||||||||||||||||||||
| "type": "struct", | ||||||||||||||||||||||||||||||
| "optional": true, | ||||||||||||||||||||||||||||||
| "name": "{{ClusterID}}.{{SchemaName}}.{{TableName}}Value", | ||||||||||||||||||||||||||||||
| "fields": [ | ||||||||||||||||||||||||||||||
| {{RowFields}} | ||||||||||||||||||||||||||||||
| ] | ||||||||||||||||||||||||||||||
| }, | ||||||||||||||||||||||||||||||
| { | ||||||||||||||||||||||||||||||
| "field": "source", | ||||||||||||||||||||||||||||||
| "type": "struct", | ||||||||||||||||||||||||||||||
| "optional": false, | ||||||||||||||||||||||||||||||
| "name": "{{ClusterID}}.{{SchemaName}}.Source", | ||||||||||||||||||||||||||||||
| "fields": [ | ||||||||||||||||||||||||||||||
| ... | ||||||||||||||||||||||||||||||
| ] | ||||||||||||||||||||||||||||||
| }, | ||||||||||||||||||||||||||||||
| { | ||||||||||||||||||||||||||||||
| "field": "op", | ||||||||||||||||||||||||||||||
| "type": "string", | ||||||||||||||||||||||||||||||
| "optional": false | ||||||||||||||||||||||||||||||
| }, | ||||||||||||||||||||||||||||||
| { | ||||||||||||||||||||||||||||||
| "field": "ts_ms", | ||||||||||||||||||||||||||||||
| "type": "int64", | ||||||||||||||||||||||||||||||
| "optional": false | ||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||
| ] | ||||||||||||||||||||||||||||||
| }, | ||||||||||||||||||||||||||||||
| "payload": { | ||||||||||||||||||||||||||||||
| "source": { | ||||||||||||||||||||||||||||||
| "version": "2.4.0.Final", | ||||||||||||||||||||||||||||||
| "connector": "TiCDC", | ||||||||||||||||||||||||||||||
| "name": "default", | ||||||||||||||||||||||||||||||
| "ts_ms": 1707103832263, | ||||||||||||||||||||||||||||||
| "snapshot": null, | ||||||||||||||||||||||||||||||
| "db": "test", | ||||||||||||||||||||||||||||||
| "table": "t2", | ||||||||||||||||||||||||||||||
| "server_id": 0, | ||||||||||||||||||||||||||||||
| "file": "", | ||||||||||||||||||||||||||||||
| "pos": 0, | ||||||||||||||||||||||||||||||
| "row": 0, | ||||||||||||||||||||||||||||||
| "gtid": null, | ||||||||||||||||||||||||||||||
| "query": null, | ||||||||||||||||||||||||||||||
| "thread": null, | ||||||||||||||||||||||||||||||
| "commit_ts": 447507027004751877, | ||||||||||||||||||||||||||||||
| "cluster_id": "default" | ||||||||||||||||||||||||||||||
| }, | ||||||||||||||||||||||||||||||
| "ts_ms": 1707103832957, | ||||||||||||||||||||||||||||||
| "op": "c", | ||||||||||||||||||||||||||||||
| "before": null, | ||||||||||||||||||||||||||||||
| "after": { | ||||||||||||||||||||||||||||||
| "{{ClusterID}}.{{SchemaName}}.{{TableName}}": { | ||||||||||||||||||||||||||||||
| "id": 1, | ||||||||||||||||||||||||||||||
| "name": "Alice" | ||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||
| ``` | ||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||
| #### Avro record naming (value) | ||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||
| For value-related records, TiCDC applies the same conversion rule: | ||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||
| - Envelope `connect.name`: `{{ClusterID}}.{{SchemaName}}.{{TableName}}Envelope` | ||||||||||||||||||||||||||||||
| - Envelope Avro `name`: `{{TableName}}Envelope` | ||||||||||||||||||||||||||||||
| - Envelope Avro `namespace`: `{{ClusterID}}.{{SchemaName}}` | ||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||
| Nested row records follow the same pattern (for example, `{{TableName}}` under the same namespace). | ||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||
| Debezium Avro encodes DML event types as follows: | ||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||
| - For insert events, `op = "c"`, `before = null`, and `after` contains new row data. | ||||||||||||||||||||||||||||||
| - For update events, `op = "u"`, and `after` contains updated row data. If old value output is enabled, `before` is included. | ||||||||||||||||||||||||||||||
| - For delete events, `op = "d"`, `after = null`, and `before` contains deleted row data. | ||||||||||||||||||||||||||||||
|
Comment on lines
+172
to
+184
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Let's use active voice, add appropriate articles, and capitalize the event types ('Insert', 'Update', 'Delete') to maintain consistency with the rest of the TiCDC documentation.
Suggested change
References
|
||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||
| ## Configuration | ||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||
| The following parameters affect Debezium Avro: | ||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||
| | Parameter | Description | Default | | ||||||||||||||||||||||||||||||
| | ------------------------------------ | --------------------------------------------------------------------------------------------------------------------- | --------- | | ||||||||||||||||||||||||||||||
| | `protocol=debezium-avro` | Enables the Debezium Avro protocol | N/A | | ||||||||||||||||||||||||||||||
| | `schema-registry` | Confluent Schema Registry URL | Required | | ||||||||||||||||||||||||||||||
| | `enable-tidb-extension` | Adds TiDB-specific metadata such as `tidb_type`, and enables internal watermark / DDL encoding paths when used with `avro-enable-watermark` | `false` | | ||||||||||||||||||||||||||||||
| | `avro-decimal-handling-mode` | Decimal handling mode, `precise` or `string` | `precise` | | ||||||||||||||||||||||||||||||
| | `avro-bigint-unsigned-handling-mode` | Unsigned BIGINT handling mode, `long` or `string` | `long` | | ||||||||||||||||||||||||||||||
| | `avro-enable-watermark` | Enables watermark / DDL messages for internal testing | `false` | | ||||||||||||||||||||||||||||||
|
Comment on lines
+190
to
+197
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Let's improve the parameter descriptions in the table by using active voice, adding articles, and ending descriptions with periods for consistency.
Suggested change
References
|
||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||
| The `debezium-output-old-value` setting is controlled by sink configuration and decides whether update events include old row values in `before`. | ||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||
| `enable-tidb-extension` is optional in normal Debezium Avro scenarios. Base Debezium envelope fields are available without it. | ||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||
| ### Constraints | ||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||
| - Debezium Avro requires a Schema Registry endpoint. | ||||||||||||||||||||||||||||||
| - A Kafka topic should carry one table schema. | ||||||||||||||||||||||||||||||
| - `force-replicate` must be disabled when using Avro or Debezium Avro. | ||||||||||||||||||||||||||||||
|
Comment on lines
+199
to
+207
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Let's use active voice and second person ('you') to make the constraints and configuration descriptions clearer and more direct.
Suggested change
References
|
||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||
| ## DDL events and schema changes | ||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||
| Debezium Avro does not rely on downstream DDL event consumption. When table schema changes, TiCDC generates and registers new schemas through Schema Registry during DML processing. | ||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||
| If schema compatibility checks fail in Schema Registry, changefeed enters an error state. | ||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||
| For operational details, read: | ||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||
| - [TiCDC Avro Protocol - DDL events and schema changes](/ticdc/ticdc-avro-protocol.md#ddl-events-and-schema-changes) | ||||||||||||||||||||||||||||||
|
Comment on lines
+209
to
+217
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Let's add appropriate articles and use 'see' instead of 'read' for referring to other sections, which is more standard in technical documentation.
Suggested change
References
|
||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||
| ## Data type mapping | ||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||
| Debezium Avro follows Debezium-style type semantics, with TiCDC-specific behavior controlled by Avro options such as decimal and unsigned bigint handling. | ||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||
| For exact type mapping details and differences, see: | ||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||
| - [TiCDC Debezium Protocol - Data type mapping](/ticdc/ticdc-debezium.md#data-type-mapping) | ||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||
| ## Consumer implementation | ||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||
| Use Confluent-compatible Avro deserializers and Schema Registry APIs to decode message payloads. | ||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||
| Reference: | ||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||
| - [TiCDC Avro Protocol - Consumer implementation](/ticdc/ticdc-avro-protocol.md#consumer-implementation) | ||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||
| ## Compatibility | ||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||
| Schema evolution compatibility is determined by Schema Registry policy. Incompatible schema changes can stop the changefeed. | ||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||
| Reference: | ||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||
| - [TiCDC Avro Protocol - Compatibility](/ticdc/ticdc-avro-protocol.md#compatibility) | ||||||||||||||||||||||||||||||
|
Comment on lines
+235
to
+241
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Let's use active voice and add a newline at the end of the file to follow standard POSIX file formatting.
Suggested change
References
|
||||||||||||||||||||||||||||||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
According to the technical writing style guide, we should prefer active voice and ensure consistent terminology. Let's use active voice, correct 'schema ids' to 'schema IDs', and add appropriate articles ('the') for better clarity.
References