介绍

之前写过Flink CDC sink 到 Iceberg中,本篇主要实践如何CDC到hudi中.

什么是hudi?

Hudi is a rich platform to build streaming data lakes with incremental data pipelines

on a self-managing database layer, while being optimized for lake engines and regular batch processing.

hudi 主要解决什么问题?

  • HDFS的可伸缩性限制
  • 需要在Hadoop中更快地呈现数据
  • 没有直接支持对现有数据的更新和删除
  • 快速的ETL和建模
  • 要检索所有更新的记录,无论这些更新是添加到最近日期分区的新记录还是对旧数据的更新,Hudi都允许用户使用最后一个检查点时间戳。此过程不用执行扫描整个源表的查询

hudi的特性:

  • Upserts, Deletes with fast, pluggable indexing.
  • Incremental queries, Record level change streams
  • Transactions, Rollbacks, Concurrency Control.
  • SQL Read/Writes from Spark, Presto, Trino, Hive & more
  • Automatic file sizing, data clustering, compactions, cleaning.
  • Streaming ingestion, Built-in CDC sources & tools.
  • Built-in metadata tracking for scalable storage access.
  • Backwards compatible schema evolution and enforcement.

Flink CDC 与 Hudi整合

版本

Flink: 1.13.1

Hudi: 0.10.1

环境搭建

使用本地环境, hadoop 使用之前虚拟机安装的环境

MySQL Docker 安装个镜像,主要用于模拟数据变更,产生binlog数据

  1. dockerpull mysql:latest
  2.  
  3. docker run -itd--name mysql -p 3306:3306 -e MYSQL_ROOT_PASSWORD=123456 mysql
  4.  
  5. 进入容器,可以使用mysql连接验证:
  6.  
  7. dockerexec -it 07e946b1fa9a /bin/bash
  8.  
  9.  
  10. mysql -uroot -p123456

创建MySQL表:

  1. createtable users
  2. (
  3.     id bigint auto_increment primary key,
  4.     name varchar(20) null,
  5.     birthday timestamp defaultCURRENT_TIMESTAMP not null,
  6.     ts timestamp defaultCURRENT_TIMESTAMP not null,
  7.     sex int
  8. );

整合代码实践

pom.xml:

  1. <?xml version="1.0" encoding="UTF-8"?>
  2. <project xmlns="http://maven.apache.org/POM/4.0.0"
  3. xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  4. xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
  5. <modelVersion>4.0.0</modelVersion>
  6. <groupId>com.chaplinthink</groupId>
  7. <artifactId>flink-hudi</artifactId>
  8. <version>1.0-SNAPSHOT</version>
  9. <properties>
  10. <maven.compiler.source>8</maven.compiler.source>
  11. <maven.compiler.target>8</maven.compiler.target>
  12. </properties>
  13. <dependencies>
  14. <dependency>
  15. <groupId>org.apache.hadoop</groupId>
  16. <artifactId>hadoop-client</artifactId>
  17. <version>3.2.1</version>
  18. </dependency>
  19. <dependency>
  20. <groupId>org.apache.hadoop</groupId>
  21. <artifactId>hadoop-hdfs</artifactId>
  22. <version>3.2.1</version>
  23. <exclusions>
  24. <exclusion>
  25. <groupId>javax.servlet</groupId>
  26. <artifactId>servlet-api</artifactId>
  27. </exclusion>
  28. </exclusions>
  29. </dependency>
  30. <dependency>
  31. <groupId>org.apache.hadoop</groupId>
  32. <artifactId>hadoop-common</artifactId>
  33. <version>3.2.1</version>
  34. </dependency>
  35. <dependency>
  36. <groupId>org.apache.flink</groupId>
  37. <artifactId>flink-core</artifactId>
  38. <version>1.13.1</version>
  39. </dependency>
  40. <dependency>
  41. <groupId>org.apache.flink</groupId>
  42. <artifactId>flink-streaming-java_2.11</artifactId>
  43. <version>1.13.1</version>
  44. </dependency> <!-- <dependency>--> <!-- <groupId>org.apache.flink</groupId>--> <!-- <artifactId>flink-jdbc_2.12</artifactId>--> <!-- <version>1.10.3</version>--> <!-- </dependency>-->
  45. <dependency>
  46. <groupId>org.apache.flink</groupId>
  47. <artifactId>flink-connector-jdbc_2.11</artifactId>
  48. <version>1.13.1</version>
  49. </dependency>
  50. <dependency>
  51. <groupId>org.apache.flink</groupId>
  52. <artifactId>flink-java</artifactId>
  53. <version>1.13.1</version>
  54. </dependency>
  55. <dependency>
  56. <groupId>org.apache.flink</groupId>
  57. <artifactId>flink-clients_2.11</artifactId>
  58. <version>1.13.1</version>
  59. </dependency>
  60. <dependency>
  61. <groupId>org.apache.flink</groupId>
  62. <artifactId>flink-table-api-java-bridge_2.11</artifactId>
  63. <version>1.13.1</version>
  64. </dependency>
  65. <dependency>
  66. <groupId>org.apache.flink</groupId>
  67. <artifactId>flink-table-common</artifactId>
  68. <version>1.13.1</version>
  69. </dependency>
  70. <dependency>
  71. <groupId>org.apache.flink</groupId>
  72. <artifactId>flink-table-planner_2.11</artifactId>
  73. <version>1.13.1</version>
  74. </dependency>
  75. <dependency>
  76. <groupId>org.apache.flink</groupId>
  77. <artifactId>flink-table-planner-blink_2.11</artifactId>
  78. <version>1.13.1</version>
  79. </dependency>
  80. <dependency>
  81. <groupId>org.apache.flink</groupId>
  82. <artifactId>flink-table-planner-blink_2.11</artifactId>
  83. <version>1.13.1</version>
  84. <type>test-jar</type>
  85. </dependency>
  86. <dependency>
  87. <groupId>org.apache.flink</groupId>
  88. <artifactId>flink-runtime-web_2.11</artifactId>
  89. <version>1.13.1</version>
  90. </dependency>
  91. <dependency>
  92. <groupId>com.ververica</groupId>
  93. <!-- add the dependency matching your database -->
  94. <artifactId>flink-sql-connector-mysql-cdc</artifactId>
  95. <!-- The dependency is available only for stable releases, SNAPSHOT dependency need build by yourself. -->
  96. <version>2.2.0</version>
  97. </dependency>
  98. <!-- <dependency>-->
  99. <!-- <groupId>com.alibaba.ververica</groupId>-->
  100. <!-- <artifactId>flink-connector-mysql-cdc</artifactId>-->
  101. <!-- <version>1.2.0</version>-->
  102. <!-- </dependency>-->
  103. <dependency>
  104. <groupId>org.apache.hudi</groupId>
  105. <artifactId>hudi-flink-bundle_2.11</artifactId>
  106. <version>0.10.1</version>
  107. </dependency>
  108. <dependency>
  109. <groupId>mysql</groupId>
  110. <artifactId>mysql-connector-java</artifactId>
  111. <version>5.1.49</version>
  112. </dependency>
  113. </dependencies>
  114. </project>

使用FlinkSQL 创建MySQL数据源表、Hudi目标表,通过

INSERT INTO hudi_users2 SELECT *, DATE_FORMAT(birthday, 'yyyyMMdd') FROM mysql_users 将数据写入hudi

核心代码:

  1. final EnvironmentSettings fsSettings = EnvironmentSettings.newInstance()
  2. .useBlinkPlanner()
  3. .inStreamingMode()
  4. .build();
  5. final StreamExecutionEnvironment environment = StreamExecutionEnvironment.getExecutionEnvironment();
  6. environment.setParallelism(1);
  7. environment.enableCheckpointing(3000);
  8. final StreamTableEnvironment tableEnvironment = StreamTableEnvironment.create(environment, fsSettings);
  9. tableEnvironment.getConfig().setSqlDialect(SqlDialect.DEFAULT);
  10. // 数据源表
  11. String sourceDDL = "CREATE TABLE mysql_users (\n" +
  12. " id BIGINT PRIMARY KEY NOT ENFORCED ,\n" +
  13. " name STRING,\n" +
  14. " birthday TIMESTAMP(3),\n" +
  15. " ts TIMESTAMP(3)\n" +
  16. ") WITH (\n" +
  17. " 'connector' = 'mysql-cdc',\n" +
  18. " 'hostname' = '192.168.70.3',\n" +
  19. " 'port' = '3306', " +
  20. " 'username' = 'aa',\n" +
  21. " 'password' = 'aa', " +
  22. " 'server-time-zone' = 'Asia/Shanghai'," +
  23. " 'database-name' = 'test',\n" +
  24. " 'table-name' = 'users'\n" +
  25. " )";
  26. /**
  27. * 触发器策略是在完成五次提交后执行压缩
  28. */
  29. // 输出目标表
  30. String sinkDDL = "CREATE TABLE hudi_users2\n" +
  31. "(\n" +
  32. " id BIGINT PRIMARY KEY NOT ENFORCED,\n" +
  33. " name STRING,\n" +
  34. " birthday TIMESTAMP(3),\n" +
  35. " ts TIMESTAMP(3),\n" +
  36. " `partition` VARCHAR(20)\n" +
  37. ") PARTITIONED BY (`partition`) WITH (\n" +
  38. " 'connector' = 'hudi',\n" +
  39. " 'table.type' = 'MERGE_ON_READ',\n" +
  40. " 'path' = 'hdfs://ip:8020/hudi/hudi_users2'\n " +
  41. ")";
  42. String transformSQL = "INSERT INTO hudi_users2 SELECT *, DATE_FORMAT(birthday, 'yyyyMMdd') FROM mysql_users\n";
  43. tableEnvironment.executeSql(sourceDDL);
  44. tableEnvironment.executeSql(sinkDDL);
  45. tableEnvironment.executeSql(transformSQL);
  46. environment.execute("mysql-to-hudi");

本地启动Flink程序

然后进行MySQL DML 操作

  1. insertinto users (name) values ('hello');
  2. insertinto users (name) values ('world');
  3. insertinto users (name) values ('iceberg');
  4. insertinto users (name) values ('hudi');
  5. update users set name = 'hello spark' where id = 4;
  6. delete from users where id = 5;

查看HDFS上hudi数据路径:

Hudi 默认情况下,MERGE_ON_READ表的压缩是启用的, 触发器策略是在完成五次提交后执行压缩. 在MySQL执行insert、update、delete等操作后,就可以用hive/spark-sql/presto进行查询。

如果没有生成parquet文件,我们建的parquet表是查询不出数据的。

五次提交后可以看到数据文件:

关掉Flink CDC程序,  单独写个FlinkSQL程序读取HDFS 上hudi数据:

  1. public static void main(String[] args) throwsException {
  2.         final EnvironmentSettings fsSettings =EnvironmentSettings.newInstance().useBlinkPlanner().inStreamingMode().build();
  3.         final StreamExecutionEnvironmentenvironment = StreamExecutionEnvironment.getExecutionEnvironment();
  4.         environment.setParallelism(1);
  5.         final StreamTableEnvironmenttableEnvironment = StreamTableEnvironment.create(environment, fsSettings);
  6.        tableEnvironment.getConfig().setSqlDialect(SqlDialect.DEFAULT);
  7.  
  8.         String sourceDDL = "CREATE TABLEhudi_users2\n" +
  9.                 "(\n" +
  10.                 "    id BIGINT PRIMARY KEY NOT ENFORCED,\n"+
  11.                 "    name STRING,\n" +
  12.                 "    birthday TIMESTAMP(3),\n" +
  13.                 "    ts TIMESTAMP(3),\n" +
  14.                 "    `partition` VARCHAR(20)\n" +
  15.                 ") PARTITIONED BY(`partition`) WITH (\n" +
  16.                 "    'connector' = 'hudi',\n" +
  17.                 "    'table.type' = 'MERGE_ON_READ',\n" +
  18.                 "    'path' ='hdfs://ip:8020/hudi/hudi_users2',\n" +
  19.                 "    'read.streaming.enabled' = 'true',\n"+
  20.                 "    'read.streaming.check-interval' = '1'\n" +
  21.                 ")";
  22.         tableEnvironment.executeSql(sourceDDL);
  23.         TableResult result2 =tableEnvironment.executeSql("select * from hudi_users2");
  24.         result2.print();
  25.  
  26.        environment.execute("read_hudi");
  27.     }

FlinkSQL读取到打印的数据:

与MySQL 数据库表数据比对可以看到数据是一致的:

至此flink + hudi 湖仓一体化方案的原型就构建完成了.

总结

本篇主要讲解Flink CDC与hudi整合实践, 探索新的湖仓一体架构, 业内37手游的湖仓一体架构也可供参考如下:

对频繁增加表字段的痛点需求,同步下游系统的时候希望能够自动加入这个字段,目前还没有完美的解决方案,Flink CDC社区后续看是否提供 Schema Evolution 的支持.

目前MySQL新增字段,是需要修改Flink程序,然后重启.

参考:

  1. https://hudi.apache.org/cn/
  2. https://cloud.tencent.com/developer/article/1884134
  3. https://developer.aliyun.com/article/791526

Flink CDC 与Hudi整合的更多相关文章

  1. 重磅!解锁Apache Flink读写Apache Hudi新姿势

    感谢阿里云 Blink 团队Danny Chan的投稿及完善Flink与Hudi集成工作. 1. 背景 Apache Hudi 是目前最流行的数据湖解决方案之一,Data Lake Analytics ...

  2. Fllin(七)【Flink CDC实践】

    目录 FlinkCDC 1.简介 2.依赖 3.flink stream api 4.flink sql 5.自定义反序列化器 6.打包测试 FlinkCDC 1.简介 CDC是Change Data ...

  3. 使用Apache Flink 和 Apache Hudi 创建低延迟数据湖管道

    近年来出现了从单体架构向微服务架构的转变.微服务架构使应用程序更容易扩展和更快地开发,支持创新并加快新功能上线时间.但是这种方法会导致数据存在于不同的孤岛中,这使得执行分析变得困难.为了获得更深入和更 ...

  4. 基于Apache Hudi 的CDC数据入湖

    作者:李少锋 文章目录: 一.CDC背景介绍 二.CDC数据入湖 三.Hudi核心设计 四.Hudi未来规划 1. CDC背景介绍 首先我们介绍什么是CDC?CDC的全称是Change data Ca ...

  5. 基于Apache Hudi + Flink的亿级数据入湖实践

    本次分享分为5个部分介绍Apache Hudi的应用与实践 实时数据落地需求演进 基于Spark+Hudi的实时数据落地应用实践 基于Flink自定义实时数据落地实践 基于Flink+Hudi的应用实 ...

  6. Apache Hudi与Apache Flink集成

    感谢王祥虎@wangxianghu 投稿 Apache Hudi是由Uber开发并开源的数据湖框架,它于2019年1月进入Apache孵化器孵化,次年5月份顺利毕业晋升为Apache顶级项目.是当前最 ...

  7. Apache Hudi核心概念一网打尽

    1. 场景 https://hudi.apache.org/docs/use_cases.html 近实时写入 减少碎片化工具的使用 CDC 增量导入 RDBMS 数据 限制小文件的大小和数量 近实时 ...

  8. Apache Hudi C位!云计算一哥AWS EMR 2020年度回顾

    1. 概述 成千上万的客户在Amazon EMR上使用Apache Spark,Apache Hive,Apache HBase,Apache Flink,Apache Hudi和Presto运行大规 ...

  9. 对话Apache Hudi VP, 洞悉数据湖的过去现在和未来

    Apache Hudi是一个开源数据湖管理平台,用于简化增量数据处理和数据管道开发,该平台可以有效地管理业务需求,例如数据生命周期,并提高数据质量.Hudi的一些常见用例是记录级的插入.更新和删除.简 ...

  10. 触宝科技基于Apache Hudi的流批一体架构实践

    1. 前言 当前公司的大数据实时链路如下图,数据源是MySQL数据库,然后通过Binlog Query的方式消费或者直接客户端采集到Kafka,最终通过基于Spark/Flink实现的批流一体计算引擎 ...

随机推荐

  1. MFC的CBitmapButton的使用指南

    注意:此按钮使用前应该将按钮的属性:Owner Draw->True 注意:此按钮使用前应该将按钮的属性:Owner Draw->True 注意:此按钮使用前应该将按钮的属性:Owner ...

  2. 01-canvas体验

    1 <!DOCTYPE html> 2 <html lang="en"> 3 <head> 4 <meta charset="U ...

  3. 轻松易懂,一文告诉你什么是http协议?

    阅读本文之前,请详细阅读以下几篇文章: <一文包你学会网络数据抓包> <教你如何抓取网络中的数据包!黑客必备技能> 一.什么是http? Http协议即超文本传送协议 (HTT ...

  4. Linux 检查端口监听情况

    使用 lsof $ sudo lsof -i :22 COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME sshd 963 root 3u IPv4 ...

  5. vue源码解析-实现一个基础的MVVM框架

    基本介绍 vue.js采用数据劫持结合发布-订阅模式的方式,通过Object.defineProperty()来劫持各个属性的getter,setter,在数据变动时发布消息给订阅者,触发响应的监听回 ...

  6. JavaScript – Symbol

    前言 Symbol 是 es6 的特性. 如果只是写业务逻辑代码, 其实是不太会用到的. 如果是做架构, 封装, UI 组件才有需要. 但学它的概念是好的. es6 有需要内置的 Symbol 链接者 ...

  7. CSS & JS Effect – Image hover animation

    效果 效果来自: webflow 的一个模板 需求解释 有 3 给元素, 图片, overlay(黑影), link mouse enter 的时候, 图片要 zoom in. overlay 要 f ...

  8. MyBatisPlus——简介

    概述 MyBatisPlus(简称MP)是基于MyBatisPlus框架基础上开发的增强型工具,旨在简化开发.提高效率 国内开发的技术 特性 无侵入:只做增强不做改变,不会对现有工程产生影响 强大的C ...

  9. 补天云全网独有技术和唯一实用工具:QT6框架QML源码保护工具应用 QML和JavaScript源码隐藏工具

    如何保护和隐藏你的QT应用中的QML源代码?补天云全网独有技术和唯一实用工具:QT6框架QML源码保护工具应用 QML和JavaScript源码隐藏工具 简介 在通常的QT QML应用程序中,QML语 ...

  10. Flutter Engage China 开发者常见问题解答 | 上篇

    再次感谢大家对 Flutter Engage China 活动 的关注和积极参与!我们在活动前后收到了很多来自开发者的反馈和问题,Flutter 团队和演讲嘉宾在直播 Q&A 环节中也针对部分 ...