Flink CDC系列之:Kafka的Debezium JSON 结构定义类DebeziumJsonStruct

这是一个 Debezium JSON 结构定义类,使用枚举来定义 Debezium JSON 格式的字段结构和位置信息。

类概述

java 复制代码
public class DebeziumJsonStruct

这个类通过嵌套枚举定义了 Debezium JSON 格式的完整结构,包括字段名称和位置信息。

嵌套枚举详解
DebeziumStruct - 顶层结构

java 复制代码
enum DebeziumStruct {
    SCHEMA(0, "schema"),
    PAYLOAD(1, "payload");

作用:定义 Debezium JSON 的顶层结构字段。

字段说明:

  • SCHEMA(0, "schema"):表结构信息(位置0,字段名"schema")
  • PAYLOAD(1, "payload"):数据负载信息(位置1,字段名"payload")

对应的 JSON 结构:

java 复制代码
{
  "schema": { ... },    // SCHEMA 字段
  "payload": { ... }    // PAYLOAD 字段
}

DebeziumPayload - 数据负载结构

java 复制代码
enum DebeziumPayload {
    BEFORE(0, "before"),
    AFTER(1, "after"),
    OPERATION(2, "op"),
    SOURCE(3, "source");

作用:定义 payload 对象内部的字段结构。

字段说明:

  • BEFORE(0, "before"):变更前的数据(位置0,字段名"before")
  • AFTER(1, "after"):变更后的数据(位置1,字段名"after")
  • OPERATION(2, "op"):操作类型(位置2,字段名"op")
  • SOURCE(3, "source"):源数据库信息(位置3,字段名"source")

对应的 JSON 结构:

java 复制代码
{
  "payload": {
    "before": { ... },      // BEFORE 字段
    "after": { ... },       // AFTER 字段  
    "op": "c",             // OPERATION 字段
    "source": { ... }      // SOURCE 字段
  }
}

DebeziumSource - 源信息结构

java 复制代码
enum DebeziumSource {
    DATABASE(0, "db"),
    TABLE(1, "table");

作用:定义 source 对象内部的字段结构。

字段说明:

  • DATABASE(0, "db"):数据库名称(位置0,字段名"db")
  • TABLE(1, "table"):表名称(位置1,字段名"table")

对应的 JSON 结构:

java 复制代码
{
  "source": {
    "db": "inventory",     // DATABASE 字段
    "table": "users"       // TABLE 字段
  }
}

枚举设计特点

位置和名称双重映射

java 复制代码
private final int position;    // 位置索引
private final String fieldName; // 字段名称

优势:

  • 可以通过位置快速访问
  • 可以通过名称清晰标识

类型安全

使用枚举替代字符串常量,避免拼写错误:

java 复制代码
// 安全的方式
DebeziumPayload.BEFORE.getFieldName()  // 返回 "before"

// 不安全的方式(容易拼错)
String field = "befor";  // 拼写错误

易于扩展

添加新字段只需在对应枚举中添加新值:

java 复制代码
enum DebeziumPayload {
    // 现有字段...
    TIMESTAMP(4, "ts_ms"),      // 新增时间戳字段
    TRANSACTION(5, "transaction"); // 新增事务字段

实际使用场景

在序列化器中的使用

java 复制代码
public class DebeziumJsonSerializationSchema {
    
    public byte[] serialize(Event event) {
        // 构建 Debezium JSON 结构
        ObjectNode rootNode = objectMapper.createObjectNode();
        
        // 使用枚举确保字段名称一致
        rootNode.set(
            DebeziumStruct.SCHEMA.getFieldName(), 
            buildSchemaNode()
        );
        
        rootNode.set(
            DebeziumStruct.PAYLOAD.getFieldName(),
            buildPayloadNode(event)
        );
        
        return objectMapper.writeValueAsBytes(rootNode);
    }
    
    private ObjectNode buildPayloadNode(Event event) {
        ObjectNode payloadNode = objectMapper.createObjectNode();
        
        // 设置操作类型
        payloadNode.put(
            DebeziumPayload.OPERATION.getFieldName(),
            getOperationCode(event.op())
        );
        
        // 设置前后数据
        payloadNode.set(
            DebeziumPayload.BEFORE.getFieldName(),
            convertToJson(event.before())
        );
        
        payloadNode.set(
            DebeziumPayload.AFTER.getFieldName(), 
            convertToJson(event.after())
        );
        
        // 设置源信息
        payloadNode.set(
            DebeziumPayload.SOURCE.getFieldName(),
            buildSourceNode(event.tableId())
        );
        
        return payloadNode;
    }
    
    private ObjectNode buildSourceNode(TableId tableId) {
        ObjectNode sourceNode = objectMapper.createObjectNode();
        
        sourceNode.put(
            DebeziumSource.DATABASE.getFieldName(),
            tableId.getSchemaName()
        );
        
        sourceNode.put(
            DebeziumSource.TABLE.getFieldName(),
            tableId.getTableName()
        );
        
        return sourceNode;
    }
}

在反序列化器中的使用

java 复制代码
public class DebeziumJsonDeserializationSchema {
    
    public Event deserialize(byte[] message) {
        JsonNode rootNode = objectMapper.readTree(message);
        
        // 使用枚举字段名获取节点
        JsonNode payloadNode = rootNode.get(
            DebeziumStruct.PAYLOAD.getFieldName()
        );
        
        // 解析操作类型
        String operation = payloadNode.get(
            DebeziumPayload.OPERATION.getFieldName()
        ).asText();
        
        // 解析源信息
        JsonNode sourceNode = payloadNode.get(
            DebeziumPayload.SOURCE.getFieldName()
        );
        
        String database = sourceNode.get(
            DebeziumSource.DATABASE.getFieldName()
        ).asText();
        
        String table = sourceNode.get(
            DebeziumSource.TABLE.getFieldName()
        ).asText();
        
        // ... 其他解析逻辑
    }
}

生成的完整 JSON 示例

基于这个结构定义,会生成如下格式的 JSON:

java 复制代码
{
  "schema": {
    "type": "struct",
    "fields": [
      {
        "type": "struct",
        "fields": [
          {"type": "int32", "optional": false, "field": "id"},
          {"type": "string", "optional": true, "field": "name"}
        ],
        "optional": true,
        "name": "mysql-server-1.inventory.users.Value",
        "field": "before"
      }
    ],
    "optional": false,
    "name": "mysql-server-1.inventory.users.Envelope"
  },
  "payload": {
    "before": null,
    "after": {
      "id": 1001,
      "name": "张三"
    },
    "op": "c",
    "source": {
      "db": "inventory",
      "table": "users"
    }
  }
}

扩展建议

当前定义比较基础,实际 Debezium 格式包含更多字段,可以扩展为:

java 复制代码
enum DebeziumPayload {
    BEFORE(0, "before"),
    AFTER(1, "after"), 
    OPERATION(2, "op"),
    SOURCE(3, "source"),
    TIMESTAMP(4, "ts_ms"),
    TRANSACTION(5, "transaction");
}

enum DebeziumSource {
    DATABASE(0, "db"),
    TABLE(1, "table"),
    SERVER_ID(2, "server_id"),
    BINLOG_FILE(3, "file"),
    BINLOG_POSITION(4, "pos"),
    CONNECTOR(5, "connector"),
    SNAPSHOT(6, "snapshot");
}

总结:DebeziumJsonStruct 是一个结构定义类,它通过嵌套枚举:

✅ 定义标准结构:完整定义 Debezium JSON 格式的字段结构

✅ 提供类型安全:使用枚举替代字符串常量,避免拼写错误

✅ 支持双向访问:既可以通过名称访问,也可以通过位置访问

✅ 易于维护扩展:集中管理字段定义,支持轻松添加新字段

✅ 提高代码可读性:清晰的枚举名称使代码意图更明确

这个类是 Debezium JSON 序列化和反序列化组件的基础,确保了数据格式的规范性和一致性。

相关推荐
最笨的羊羊44 分钟前
Flink CDC系列之:Kafka JSON 序列化类型枚举
flink cdc系列·kafka json·序列化类型枚举
最笨的羊羊16 小时前
Flink CDC系列之:数据接收器工厂类DorisDataSinkFactory
doris·flink cdc系列·数据接收器工厂类·datasinkfactory
2501_941142132 天前
前端高性能优化与微前端架构设计在大型互联网系统中的实践经验分享
kafka
20岁30年经验的码农2 天前
Kafka 消息中间件实战指南
分布式·kafka·linq
yumgpkpm2 天前
腾讯云TBDS与CDH迁移常见问题有哪些?建议由CDH迁移到CMP 7.13 平台(类Cloudera CDP,如华为鲲鹏 ARM 版)
hive·hadoop·zookeeper·flink·spark·kafka·hbase
2501_941142132 天前
基于 Kotlin 构建移动端高并发后台服务与实时数据同步系统的架构设计与工程实践分享
kafka
yumgpkpm3 天前
数据可视化AI、BI工具,开源适配 Cloudera CMP 7.3(或类 CDP 的 CMP 7.13 平台,如华为鲲鹏 ARM 版)值得推荐?
人工智能·hive·hadoop·信息可视化·kafka·开源·hbase
Zhao·o3 天前
KafkaMQ采集指标日志
运维·中间件·kafka
青靴3 天前
轻量级 CI/CD 实战(三):Kafka消费者Docker容器化部署
分布式·docker·kafka