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 天前
Apache Doris 2.1.10 集群部署与 Paimon 数据湖集成实战文档
apache·doris·paimon
鹿衔`5 天前
Apache Doris 4.0.1 集群部署与 Paimon 数据湖集成实战文档
flink·apache·doris·paimon
想ai抽9 天前
StarRocks PB 级日增量数据模型优化:注意点、调优策略与风险防控
starrocks·doris·数据湖
孟意昶11 天前
Doris专题27-mysql兼容性与join连接
大数据·数据库·分布式·sql·mysql·doris
最笨的羊羊16 天前
Flink CDC系列之:Kafka Sink 的序列化器PipelineKafkaRecordSerializationSchema
pipeline·schema·kafka sink·flink cdc系列·serialization·序列化器·kafkarecord
最笨的羊羊17 天前
Flink CDC系列之:Kafka 变更日志 JSON 格式工厂类 ChangeLogJsonFormatFactory
json·flink cdc系列·changelog·kafka 变更日志·json 格式工厂类·formatfactory
最笨的羊羊17 天前
Flink CDC系列之:Kafka Debezium JSON 序列化器的实现DebeziumJsonSerializationSchema
kafka·debezium·schema·flink cdc系列·serialization·序列化器·debezium json
FeelTouch Labs17 天前
图解Apache Doris
doris
最笨的羊羊17 天前
Flink CDC系列之:Kafka 数据接收器配置选项类KafkaDataSinkOptions
kafka·flink cdc系列·kafkadata·数据接收器配置选项类·sinkoptions
最笨的羊羊18 天前
Flink CDC系列之: Kafka 数据接收器工厂类KafkaDataSinkFactory
kafka·flink cdc系列·数据接收器工厂类·kafkadata·sinkfactory