java 实现 flink 读 kafka 写 delta

一.背景

在企业数字化转型向深度渗透的过程中,数据已成为核心生产要素,业务对数据处理的诉求逐渐升级为 "实时采集 - 统一计算 - 长期治理 - 全场景复用" 的全链路能力。日志流、交易流水、用户行为、物联网传感等实时数据持续爆发,这类数据既需要低延迟处理以支撑即时决策(如实时监控、动态营销),又需要长期可靠存储以满足离线分析、数据回溯、合规审计、模型训练等场景,传统数据架构的 "实时与离线割裂、存储治理薄弱、数据价值沉淀不足" 等痛点日益凸显。

传统架构中,Kafka 作为消息队列的核心选型,凭借高吞吐、低延迟的特性成为实时数据传输的 "枢纽",但仅适用于流式数据的短期暂存与分发,缺乏复杂查询、数据更新、版本管理等能力,无法承载数据长期复用需求;而传统数据仓库(如 Hive)虽能支撑离线分析,却存在实时写入延迟高、Schema 灵活度低、不支持事务等问题,难以适配半结构化 / 非结构化数据的存储诉求,导致 "实时处理结果难以高效沉淀,离线分析无法快速复用实时数据" 的割裂困境。同时,数据量的爆发式增长还对存储的成本控制、可扩展性、数据一致性及治理效率提出了更高要求,传统存储方案难以兼顾多维度诉求。

在此背景下,"Kafka + Flink + Delta" 的协同架构成为破解上述痛点的最优解之一,各组件形成互补、各司其职,构建起全链路数据处理能力:

  1. Kafka 作为实时数据接入核心:依托高吞吐、低延迟、高容错的核心优势,稳定承接多源实时数据流(日志、交易、传感等)的写入与分发,为后续计算环节提供持续、稳定的数据输入,是实时数据链路的 "源头枢纽";
  2. Flink 作为流批一体计算引擎:具备强大的实时数据处理能力,支持 Exactly-Once 语义、复杂事件处理(CEP)、状态管理等核心特性,可高效消费 Kafka 中的实时数据流,完成数据清洗、转换、聚合、关联等计算逻辑,同时兼顾批处理场景,是连接 "实时数据源头" 与 "长期存储终端" 的核心计算桥梁;
  3. Delta 作为湖仓一体存储方案:基于 Apache Spark 生态发展而来,以 ACID 事务为核心优势,兼具数据湖的灵活性与数据仓库的可靠性 ------ 支持实时增量写入、批量读取、数据版本控制、时间旅行(数据回溯)、Schema 演进、数据压缩与分区优化等核心能力,能够高效承接 Flink 处理后的实时数据,既满足低延迟的实时查询需求,又支持离线分析、数据归档、合规审计等场景,同时解决了传统数据湖 "数据混乱、查询低效、治理困难" 的痛点,实现数据的长期可管、可控、可复用。

Java 作为 Flink、Kafka、Delta 生态的核心开发语言,具备完善的 API 支持、成熟的企业级实践、丰富的生态工具链,能够确保架构的稳定性、可扩展性与可维护性。因此,采用 Java 实现 "Flink 读 Kafka 写 Delta" 的方案,本质是构建一套 "实时接入 - 流批一体计算 - 湖仓化存储" 的端到端数据处理闭环。该方案可广泛应用于实时数据仓库构建、用户行为全链路分析、金融交易实时归档与回溯、物联网数据实时处理与长期存储等业务场景,帮助企业打通实时与离线数据壁垒,实现数据价值的高效沉淀与灵活复用,同时降低数据存储与治理成本,为数据驱动决策提供坚实支撑。

二.具体实现

1.创建java工程,引入依赖

复制代码
        <dependency>
            <groupId>org.apache.flink</groupId>
            <artifactId>flink-java</artifactId>
            <version>1.18.1</version>
        </dependency>
        <dependency>
            <groupId>org.apache.flink</groupId>
            <artifactId>flink-streaming-java</artifactId>
            <version>1.18.1</version>
        </dependency>
        <dependency>
            <groupId>org.apache.flink</groupId>
            <artifactId>flink-clients</artifactId>
            <version>1.18.1</version>
        </dependency>
        <dependency>
            <groupId>org.apache.flink</groupId>
            <artifactId>flink-connector-kafka</artifactId>
            <version>3.0.2-1.18</version>
        </dependency>        
        <dependency>
            <groupId>org.apache.flink</groupId>
            <artifactId>flink-table-common</artifactId>
            <version>1.18.1</version>
        </dependency>
        <dependency>
            <groupId>org.apache.flink</groupId>
            <artifactId>flink-orc</artifactId>
            <version>1.18.1</version>
        </dependency>
        <dependency>
            <groupId>org.apache.hadoop</groupId>
            <artifactId>hadoop-client</artifactId>
            <version>3.3.2</version>
        </dependency>
        <dependency>
            <groupId>io.delta</groupId>
            <artifactId>delta-flink</artifactId>
            <version>3.2.0</version>
        </dependency>
        <dependency>
            <groupId>io.delta</groupId>
            <artifactId>delta-core_2.12</artifactId>
            <version>2.4.0</version>
        </dependency>

2.定义kafka数据源反序列化类

复制代码
public class DataSchemaDeserialization implements KafkaDeserializationSchema<ConsumerRecord<String,String>> {

    @Override
    public boolean isEndOfStream(ConsumerRecord<String,String> nextElement) {
        return false;
    }

    @Override
    public ConsumerRecord<String,String> deserialize(ConsumerRecord<byte[], byte[]> record) throws Exception {

        return new ConsumerRecord<String, String>(
                record.topic(),
                record.partition(),
                record.offset(),
                record.timestamp(),
                record.timestampType(),
                record.serializedKeySize(),
                record.serializedValueSize(),
                record.key() != null ? new String(record.key()) : null,
                record.value() != null ? new String(record.value(), StandardCharsets.UTF_8) : null,
                record.headers(),
                record.leaderEpoch()
        );
    }


    @Override
    public TypeInformation<ConsumerRecord<String,String>> getProducedType() {
        return TypeInformation.of(new TypeHint<ConsumerRecord<String,String>>() {
        });
    }
}

3.定义kafka数据源(json格式)

复制代码
Properties props = new Properties();
        props.put(CommonClientConfigs.BOOTSTRAP_SERVERS_CONFIG,kafka地址);
        props.put(CommonClientConfigs.GROUP_ID_CONFIG,消费组);
        props.put(ENABLE_IDEMPOTENCE_CONFIG, "true");
 
        FlinkKafkaConsumerBase flinkKafkaConsumer = new FlinkKafkaConsumer<>(kafka topic, new DataSchemaDeserialization(), props).setStartFromGroupOffsets();

4.转换数据流为RowData格式

复制代码
DataStream<RowData> data = env.addSource(flinkKafkaConsumer).map(new MapFunction<ConsumerRecord, RowData>() {
            @Override
            public RowData map(ConsumerRecord value) throws Exception {
                GenericRowData row = new GenericRowData(10);
                       ... ...                             
                return row;
            }
        });

5.定义写入配置

复制代码
Configuration configuration = new Configuration();
            configuration.set("spark.delta.logStore.s3a.impl", "io.delta.storage.S3DynamoDBLogStore");

        String[] partitionCols = {"a"}

        DeltaSink<RowData> deltaSink = DeltaSink
                .forRowData(
                        new Path(hti.getLocation()),
                        configuration,
                        rowTypeInfo)
                .withPartitionColumns(partitionCols)
                .build();

        data.sinkTo(deltaSink);
相关推荐
逆风局?43 分钟前
后端Web实战(部门管理)——日志技术
java·前端
jiayong231 小时前
Elasticsearch 分词器完全指南:原理、类型与实战
大数据·elasticsearch·搜索引擎
小马爱打代码1 小时前
Spring AI:ChatClient实现对话效果
java·人工智能·spring
科技测评-阿博1 小时前
深度解析:如何选择高效获客软件以加速企业级应用开发
大数据·人工智能
zzhongcy1 小时前
RocketMQ、Kafka 和 RabbitMQ 等中间件对比
kafka·rabbitmq·rocketmq
无敌最俊朗@1 小时前
C++ 内存管理与编译原理 (面试复习2)
java·开发语言·jvm
赴前尘1 小时前
docker 配置ipv6地址
java·docker·容器
良策金宝AI1 小时前
工程AI ≠ 通用大模型:为什么电力设计需要垂直行业模型?
大数据·人工智能