用 Kafka 打通实时数据总线Flink CDC Pipeline 的 Kafka Sink 实战

1. 五分钟起步:MySQL → Kafka 最小可用 Pipeline

yaml 复制代码
source:
  type: mysql
  name: MySQL Source
  hostname: 127.0.0.1
  port: 3306
  username: admin
  password: pass
  tables: adb.\.*, bdb.user_table_[0-9]+, [app|web].order_\.*
  server-id: 5401-5404

sink:
  type: kafka
  name: Kafka Sink
  properties.bootstrap.servers: PLAINTEXT://localhost:62510
  # 可选:固定写入同一个 topic(否则默认按 tableId 路由)
  # topic: cdc-all
  # 可选:分区策略(默认 all-to-zero)
  # partition.strategy: hash-by-key
  # 可选:键/值编码
  # key.format: json
  # value.format: debezium-json

pipeline:
  name: MySQL to Kafka Pipeline
  parallelism: 2

易错点

  • tables 支持正则;. 是库/模式/表的分隔符 ,匹配任意字符请用 \. 转义。
  • Kafka 地址写在 properties.bootstrap.servers(可带协议前缀,如 PLAINTEXT://SASL_SSL://)。
  • 未显式配置 topic 时,默认主题名为 namespace.schemaName.tableName(即 tableId)。

2. 主题与分区:如何"稳可观测、快可扩展"

2.1 路由方式

  • 默认 :按 tableId 写入对应主题:namespace.schema.table

  • 固定主题 :设置 topic: your_topic,所有事件汇聚到一个主题(便于统一消费,但需更高吞吐与分区数)。

  • 自定义映射:细粒度把表映射到不同主题:

    yaml 复制代码
    sink.tableId-to-topic.mapping: mydb.orders:orders_cdc;mydb.users:users_cdc
  • 记录头携带表信息(便于单主题多表消费做路由/监控):

    yaml 复制代码
    sink.add-tableId-to-header-enabled: true

    将为每条记录添加 namespace/schemaName/tableName 三个 header。

2.2 分区策略

  • partition.strategy: all-to-zero(默认):全部写 0 号分区,利于单消费者串行处理与全序消费,但扩展性差。
  • partition.strategy: hash-by-key:按主键哈希 分发到多个分区,同主键有序且可横向扩展(推荐用于高吞吐)。

使用 hash-by-key 时,务必确保上游表定义了主键键序列化key.format 决定(json/csv,默认 json)。

3. 消息格式(Value)与 Schema

3.1 可选值格式

  • value.format: debezium-json(默认)

    • 字段包含 before/after/op/sourcesource 中不含 ts_ms

    • 示例:

      json 复制代码
      {
        "before": null,
        "after": { "col1": "1", "col2": "1" },
        "op": "c",
        "source": { "db": "default_namespace", "table": "table1" }
      }
    • 如需携带 schema(schema/payload 两层),开启:

      yaml 复制代码
      debezium-json.include-schema.enabled: true
  • value.format: canal-json

    • 字段包含 old/data/type/database/table/pkNames不包含 ts

    • 示例:

      json 复制代码
      {
        "old": null,
        "data": [{ "col1": "1", "col2": "1" }],
        "type": "INSERT",
        "database": "default_schema",
        "table": "table1",
        "pkNames": ["col1"]
      }

事件时间 :两种内置格式都不包含 时间戳字段,可用 Kafka Record Timestamp(Broker 侧)作为事件时间,或在消费端自行补齐。

3.2 键格式(Key)

  • key.format: json | csv(默认 json)。
  • 仅在 hash-by-key 或你在消费端需要读取 Kafka Message Key 时有意义。

3.3 自定义 Header

  • 固定追加自定义头:

    yaml 复制代码
    sink.custom-header: env:prod,team:realtime
  • 加表身份头:见 2.1 的 sink.add-tableId-to-header-enabled: true

4. Kafka Producer 常用参数(透传)

通过 properties.* 透传 Kafka Producer 配置,如:

yaml 复制代码
sink:
  type: kafka
  name: Kafka Sink
  properties.bootstrap.servers: SASL_SSL://kafka-1:9093,kafka-2:9093
  properties.acks: all
  properties.linger.ms: 20
  properties.batch.size: 524288
  properties.max.in.flight.requests.per.connection: 1
  properties.compression.type: lz4
  # 安全建议(示例,按你的集群实际为准)
  properties.security.protocol: SASL_SSL
  properties.sasl.mechanism: PLAIN
  properties.sasl.jaas.config: org.apache.kafka.common.security.plain.PlainLoginModule required username="xxx" password="yyy";

生产建议:

  • 预建主题 并指定分区数/副本因子/保留策略;自动建主题虽方便,但不可控。
  • 开启 acks=all,将 max.in.flight.requests.per.connection 设为 1 以避免乱序(吞吐换一致)。
  • 合理设置 linger.ms/batch.size/compression.type 提升吞吐与成本效率。

5. 数据类型映射(速查)

Literal type:Kafka Connect 的物理存储类型;Semantic type:Debezium 的逻辑语义。

CDC type JSON type Literal type Semantic type 备注
TINYINT TINYINT INT16 ---
SMALLINT SMALLINT INT16 ---
INT INT INT32 ---
BIGINT BIGINT INT64 ---
FLOAT FLOAT FLOAT ---
DOUBLE DOUBLE DOUBLE ---
DECIMAL(p,s) DECIMAL(p,s) BYTES org.apache.kafka.connect.data.Decimal
BOOLEAN BOOLEAN BOOLEAN ---
DATE DATE INT32 io.debezium.time.Date
TIMESTAMP§ TIMESTAMP§ INT64 p<=3: io.debezium.time.Timestampp>3: io.debezium.time.MicroTimestamp
TIMESTAMP_LTZ TIMESTAMP_LTZ STRING io.debezium.time.ZonedTimestamp
CHAR(n) CHAR(n) STRING ---
VARCHAR(n) VARCHAR(n) STRING ---

6.1 读取 Debezium-JSON

sql 复制代码
CREATE TABLE ods_orders (
  col1 STRING,
  col2 STRING,
  PRIMARY KEY (col1) NOT ENFORCED
) WITH (
  'connector' = 'kafka',
  'topic' = 'mydb.public.orders',
  'properties.bootstrap.servers' = 'kafka:9092',
  'value.format' = 'debezium-json'
);

6.2 读取 Canal-JSON

sql 复制代码
CREATE TABLE ods_orders_canal (
  col1 STRING,
  col2 STRING,
  PRIMARY KEY (col1) NOT ENFORCED
) WITH (
  'connector' = 'kafka',
  'topic' = 'mydb.public.orders',
  'properties.bootstrap.servers' = 'kafka:9092',
  'value.format' = 'canal-json'
);

若你采用单主题多表 ,可在消费端结合 tableId 头或 value 中的表名做动态路由/过滤

7. 上线 Checklist(强烈建议)

  1. 主题预创建 :为单表或汇聚主题规划分区数/副本因子/保留策略 ;打开 min.insync.replicas
  2. 分区策略 :高吞吐业务优先 hash-by-key;如需全序处理选 all-to-zero + 单消费者。
  3. 键/值格式 :若做主键幂等消费或按键路由,配置 key.format 并校验主键完整性。
  4. 格式验证 :消费端用脚本检查 value 格式与字符集;需要 schema 时开启 debezium-json.include-schema.enabled
  5. 安全与配额:开启 SASL/SSL;为生产者设置 quota 与监控,防止"风暴写入"。
  6. 可观测性:接入 Producer/Consumer 指标与 lag 监控,预设告警阈值。
  7. 回压与重启:演练任务重启与 Broker 降级,确认无数据丢失与可接受的重试延迟。

8. 常见问题(Troubleshooting)

  • 消息全都到 0 号分区 :未配置或仍使用默认 all-to-zero;改为 hash-by-key 并确保上游主键存在。
  • 消费端乱序 :检查 max.in.flight.requests.per.connection 是否 > 1;需要严格顺序时置为 1。
  • 单主题多表难以拆分 :开启 sink.add-tableId-to-header-enabled,消费端按 header 路由。
  • 需要事件时间 :两种内置格式不含 ts 字段;使用 Kafka Record Timestamp 或在消费端补齐。
  • 自动建主题分区太少:建议预创建主题并指定分区与副本,避免后续扩分区带来的数据倾斜。

小结

Kafka Sink 作为 实时数据总线 的"出口"稳定可靠:

  • 路由可选(按表、单主题、映射);
  • 分区可控(全序/可扩展);
  • 编码清晰(debezium-json/canal-json + 可选 schema);
  • 生产可用(支持 header、SASL/SSL、Producer 参数透传)。
相关推荐
周杰伦_Jay3 小时前
【日志处理方案大比拼】 Filebeat+Kafka+Flink+Spark+ES+HDFS VS ELK/AOP/RocketMQ/大厂方案
flink·spark·kafka
Hello.Reader3 小时前
用 Doris 托底实时明细与聚合Flink CDC Pipeline 的 Doris Sink 实战
大数据·flink
Hello.Reader3 小时前
从 WAL 到 Fluss->Flink CDC Postgres Connector 端到端同步实战
数据库·flink
Hello.Reader5 小时前
Flink CDC + StarRocks用 StarRocks Connector 打通实时明细与分析
数据仓库·adb·flink
q***65696 小时前
Spring Boot集成Kafka:最佳实践与详细指南
spring boot·kafka·linq
百***79461 天前
Spring集成kafka的最佳方式
spring·kafka·linq
SeaTunnel1 天前
结项报告完整版:Apache SeaTunnel 支持 Flink 引擎 Schema Evolution 功能
java·大数据·flink·开源·seatunnel
冰芒芒2 天前
Kafka-2 Kafka的特点
分布式·kafka
xc丶卡卡2 天前
Windows 系统上安装 Kafka
kafka·windoiws安装kafka