Flink CDC系列之:Doris 模式工具类DorisSchemaUtils

这是一个 Doris 模式工具类,专门用于处理 Flink CDC 到 Doris 数据同步时的自动分区配置。

java 复制代码
public class DorisSchemaUtils

这个工具类主要负责根据配置信息为 Doris 表生成自动分区策略,特别适用于时间序列数据的自动分区管理。

核心常量定义

java 复制代码
public static final String DEFAULT_DATE = "1970-01-01";
public static final String DEFAULT_DATETIME = "1970-01-01 00:00:00";
public static final String INVALID_OR_MISSING_DATATIME = "0000-00-00 00:00:00";

日期常量:用于处理默认日期和无效日期值。

核心方法详解

getPartitionInfo() - 获取分区信息

这是工具类的核心方法,根据配置生成 Doris 表的分区策略:

java 复制代码
public static Tuple2<String, String> getPartitionInfo(
        Configuration config, Schema schema, TableId tableId) {

参数说明:

  • config:Flink CDC 配置
  • schema:表结构定义
  • tableId:表标识

返回值:Tuple2<分区键, 分区单位>,如 ("create_time", "DAY")

方法执行流程

检查自动分区配置

java 复制代码
Map<String, String> autoPartitionProperties =
        DorisDataSinkOptions.getPropertiesByPrefix(
                config, TABLE_CREATE_AUTO_PARTITION_PROPERTIES_PREFIX);
if (autoPartitionProperties.isEmpty()) {
    return null;  // 没有配置自动分区,返回null
}

作用:从配置中提取所有以 table.create.auto-partition. 为前缀的配置项。

表包含/排除检查

java 复制代码
if (isExcluded(autoPartitionProperties, tableId)
        || !isIncluded(autoPartitionProperties, tableId)) {
    return null;  // 表被排除或不在包含列表中,返回null
}

获取分区键

java 复制代码
String partitionKey =
        getPartitionProperty(
                autoPartitionProperties,
                tableId,
                TABLE_CREATE_PARTITION_KEY,
                TABLE_CREATE_DEFAULT_PARTITION_KEY);
if (partitionKey == null || !schema.getColumn(partitionKey).isPresent()) {
    return null;  // 分区键不存在于表结构中
}

调用 getPartitionProperty 方法,从配置(autoPartitionProperties)中尝试获取指定的分区键。

参数说明:

  • autoPartitionProperties:存储分区相关配置的容器(如 Map<String, String>)。
  • tableId:目标表的标识符。
  • TABLE_CREATE_PARTITION_KEY:明确指定分区键的配置项。
  • TABLE_CREATE_DEFAULT_PARTITION_KEY:默认分区键的配置项(当前键不存在时可能使用)。

验证分区键的有效性

java 复制代码
if (partitionKey == null || !schema.getColumn(partitionKey).isPresent()) {
      return null;  // 分区键不存在于表结构中
  }
  • 条件1:partitionKey == null
  • 表示配置中未定义任何分区键。
  • 条件2:!schema.getColumn(partitionKey).isPresent()
  • 表示分区键的列名在表结构(schema)中不存在。
  • 如果任一条件满足,则返回 null,表示无法进行分区。

获取分区单位

java 复制代码
String partitionUnit =
        getPartitionProperty(
                autoPartitionProperties,
                tableId,
                TABLE_CREATE_PARTITION_UNIT,
                TABLE_CREATE_DEFAULT_PARTITION_UNIT);
if (partitionUnit == null) {
    return null;
}

验证数据类型并返回

java 复制代码
DataType dataType = schema.getColumn(partitionKey).get().getType();

从表结构(schema)中获取分区键(partitionKey)对应的列。

通过 getType() 获取该列的数据类型(如 INT、STRING、TIMESTAMP 等)。

验证数据类型并返回结果

java 复制代码
return isValidDataType(dataType) ? new Tuple2<>(partitionKey, partitionUnit) : null;

调用 isValidDataType(dataType) 检查该数据类型是否允许作为分区键。

如果有效:返回一个 Tuple2 对象,包含:

  • partitionKey(分区键列名)
  • partitionUnit(分区单位,如按天、按月等)
  • 如果无效:返回 null,表示该列不能作为分区键。

辅助方法详解

表排除检查 isExcluded()

java 复制代码
private static boolean isExcluded(Map<String, String> properties, TableId tableId) {
    String excludes = properties.get(TABLE_CREATE_PARTITION_EXCLUDE);
    if (!StringUtils.isNullOrWhitespaceOnly(excludes)) {
        Selectors selectExclude =
                new Selectors.SelectorsBuilder().includeTables(excludes).build();
        return selectExclude.isMatch(tableId);
    }
    return false;
}

作用:检查表是否在排除列表中。

表包含检查 isIncluded()

java 复制代码
private static boolean isIncluded(Map<String, String> properties, TableId tableId) {
    String includes = properties.get(TABLE_CREATE_PARTITION_INCLUDE);
    if (!StringUtils.isNullOrWhitespaceOnly(includes)) {
        Selectors selectInclude =
                new Selectors.SelectorsBuilder().includeTables(includes).build();
        return selectInclude.isMatch(tableId);
    }
    return true;  // 默认包含所有表
}

作用:检查表是否在包含列表中。

获取分区属性 getPartitionProperty()

java 复制代码
private static String getPartitionProperty(
        Map<String, String> properties,
        TableId tableId,
        String specificKey,
        String defaultKey) {
    String key = properties.get(tableId.identifier() + "." + specificKey);
    return StringUtils.isNullOrWhitespaceOnly(key) ? properties.get(defaultKey) : key;
}

StringUtils.isNullOrWhitespaceOnly 是一个工具方法,用于检查字符串是否为 null 或仅包含空白字符。以下是详细解释:

方法功能

  • 作用:判断输入的字符串是否为 null 或仅由空白字符(如空格、制表符、换行符等)组成。
  • 返回值:
  • true:字符串为 null 或仅包含空白字符。
  • false:字符串包含至少一个非空白字符。

优先级:先查找表特定的配置,找不到则使用默认配置。

数据类型验证 isValidDataType()

java 复制代码
private static boolean isValidDataType(DataType dataType) {
    return dataType instanceof LocalZonedTimestampType
            || dataType instanceof TimestampType
            || dataType instanceof ZonedTimestampType
            || dataType instanceof DateType;
}

支持的数据类型:只允许时间/日期类型作为分区键。

配置示例

Flink CDC 配置示例

java 复制代码
# 自动分区全局配置
table.create.auto-partition.partition-key=create_time
table.create.auto-partition.partition-unit=DAY

# 表包含/排除配置
table.create.auto-partition.include=database1.table1,database1.table2
table.create.auto-partition.exclude=database1.temp_table

# 表特定配置(优先级更高)
table.create.auto-partition.database1.table1.partition-key=update_time
table.create.auto-partition.database1.table1.partition-unit=MONTH

在 Flink CDC Pipeline 中使用

java 复制代码
mysql-sync-database \
--database source_db \
--sink-conf connector=doris \
--sink-conf fenodes=fe1:8030 \
--sink-conf username=user \
--sink-conf password=pass \
--table-create-auto-partition.partition-key=create_time \
--table-create-auto-partition.partition-unit=DAY \
--table-create-auto-partition.include="inventory.orders,inventory.products"

生成的 Doris DDL 示例

基于这个工具类的输出,会生成类似这样的 Doris 建表语句:

sql 复制代码
-- 自动生成的分区表
CREATE TABLE `target_db`.`orders` (
    `id` BIGINT,
    `order_no` VARCHAR(100),
    `create_time` DATETIME,
    `amount` DECIMAL(10,2)
) 
PARTITION BY RANGE(`create_time`)()
DISTRIBUTED BY HASH(`id`) BUCKETS 10
PROPERTIES (
    "dynamic_partition.enable" = "true",
    "dynamic_partition.time_unit" = "DAY",
    "dynamic_partition.start" = "-30",
    "dynamic_partition.end" = "3",
    "dynamic_partition.prefix" = "p",
    "dynamic_partition.buckets" = "10"
);

设计特点

  1. 灵活的配置策略
    全局默认配置:适用于所有表

表特定配置:为特定表覆盖全局配置

包含/排除机制:精确控制哪些表启用自动分区

使用场景

这个工具类主要用在以下场景:

  • 时间序列数据自动分区:如日志、监控数据按天分区
  • 大数据量表管理:自动维护历史数据分区
  • CDC 数据同步:将源库的表结构映射到 Doris 的自动分区表
  • 多租户数据隔离:不同表使用不同的分区策略

总结:这个 DorisSchemaUtils 工具类为 Flink CDC 到 Doris 的数据同步提供了强大的自动分区管理能力,通过灵活的配置机制和严格的数据类型验证,确保生成的 Doris 表具有合理且高效的分区结构。

相关推荐
最笨的羊羊5 小时前
Flink CDC系列之:flink-cdc-base模块config
flink cdc系列·config·flink-cdc-base
最笨的羊羊6 小时前
Flink CDC系列之:flink-cdc-base模块dialect
flink cdc系列·flink-cdc-base·dialect
最笨的羊羊1 天前
Flink CDC系列之:JSON 序列化器JsonRowDataSerializationSchemaUtils
json·flink cdc系列·serialization·json 序列化器·rowdata·schemautils
最笨的羊羊1 天前
Flink CDC系列之:Kafka CSV 序列化器CsvSerializationSchema
kafka·csv·schema·flink cdc系列·serialization·序列化器
最笨的羊羊1 天前
Flink CDC系列之:Kafka的Debezium JSON 结构定义类DebeziumJsonStruct
kafka·debezium·flink cdc系列·debezium json·结构定义类·jsonstruct
最笨的羊羊1 天前
Flink CDC系列之:Kafka JSON 序列化类型枚举
flink cdc系列·kafka json·序列化类型枚举
最笨的羊羊2 天前
Flink CDC系列之:数据接收器工厂类DorisDataSinkFactory
doris·flink cdc系列·数据接收器工厂类·datasinkfactory
最笨的羊羊8 天前
Flink CDC系列之:Apache Flink CDC 项目的各个模块作用
flink cdc系列·各个模块作用
Faith_xzc9 天前
Doris内存问题指南:监控、原理与高频OOM解决方案
大数据·性能优化·doris