Flink读取Kafka数据写入Hive

前言

 

本文针对数据库CDC(change data capture)场景设计,探讨基于Flink1.12最新版本提供的实时写入Hive的技术可行性,下面为本地IDEA程序案例可供参考。

一、整体思路

数据库CDC(change data capture)是实时捕获数据库中的变化数据,经过处理之后(也可能无需处理),将其更新到目标端的一种技术。为实现实时捕获,本文引入Debezium作为数据库connector,其提供了MongoDBMySQLPostgreSQLSQL ServerOracleDb2 、Cassandra 、Vitess(其中OracleDb2 、Cassandra 、Vitess连接器正在孵化中)等数据库的连接器。并通过kafka topic将各种数据库的全量数据、存量数据、增量数据发送出去。而在数据处理环节只需要创建kafka cunsumer并订阅相应topic即可获取topic中的数据。另外,Flink本身也提供了Flink SQL CDC的技术支持(由阿里巴巴技术团队伍翀 (云邪大佬)等提供,献上大佬博客地址),但其在flink 1.12发布版本中并未提供,预计将在1.13版本中提供MySQL 、PostgreSQL等数据库的支持。

第一次启动debezium时,其会扫描全表并发送schema信息以及全量数据,然后在实时捕捉变化信息(增量数据)以保证源端和目标端的数据一致性。在发送全量数据之前,首先将数据库、表等的schema信息通过history topic发送出去,并为数据库的每一张表创建一个topic,topic名为<connector name>. <database name>.<table name>,其中connector name为连接器的名称,开发者可以自定义。该topic用于发送全量数据、存量数据以及增量数据。

schema

debezium捕获到的表结构信息

schema

debezium捕获到的数据信息

二、引入依赖

<dependencies>
        <dependency>
            <groupId>org.apache.flink</groupId>
            <artifactId>flink-java</artifactId>
            <version>1.12.0</version>
        </dependency>
        <dependency>
            <groupId>org.apache.flink</groupId>
            <artifactId>flink-streaming-java_2.11</artifactId>
            <version>1.12.0</version>
        </dependency>
        <dependency>
            <groupId>org.apache.flink</groupId>
            <artifactId>flink-connector-kafka_2.11</artifactId>
            <version>1.12.0</version>
            <scope>compile</scope>
        </dependency>
        <dependency>
            <groupId>org.apache.flink</groupId>
            <artifactId>flink-shaded-hadoop-2-uber</artifactId>
            <version>2.7.5-9.0</version>
        </dependency>
        <dependency>
            <groupId>org.apache.flink</groupId>
            <artifactId>flink-sequence-file</artifactId>
            <version>1.12.0</version>
        </dependency>
        <dependency>
            <groupId>org.apache.flink</groupId>
            <artifactId>flink-table-api-java-bridge_2.11</artifactId>
            <version>1.12.0</version>
        </dependency>
        <dependency>
            <groupId>org.apache.flink</groupId>
            <artifactId>flink-table-planner-blink_2.11</artifactId>
            <version>1.12.0</version>
            <scope>compile</scope>
        </dependency>
        <dependency>
            <groupId>org.apache.flink</groupId>
            <artifactId>flink-clients_2.11</artifactId>
            <version>1.12.0</version>
            <scope>compile</scope>
        </dependency>
        <dependency>
            <groupId>org.apache.flink</groupId>
            <artifactId>flink-json</artifactId>
            <version>1.12.0</version>
            <scope>compile</scope>
        </dependency>
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>8.0.22</version>
        </dependency>
        <dependency>
            <groupId>org.apache.bahir</groupId>
            <artifactId>flink-connector-redis_2.11</artifactId>
            <version>1.0</version>
        </dependency>
        <dependency>
            <groupId>org.apache.flink</groupId>
            <artifactId>flink-connector-hive_2.11</artifactId>
            <version>1.12.0</version>
            <scope>compile</scope>
        </dependency>
        <dependency>
            <groupId>org.apache.flink</groupId>
            <artifactId>flink-table-api-java-bridge_2.11</artifactId>
            <version>1.12.0</version>
            <scope>compile</scope>
        </dependency>
        <dependency>
            <groupId>org.apache.flink</groupId>
            <artifactId>flink-streaming-scala_2.11</artifactId>
            <version>1.12.0</version>
            <scope>compile</scope>
        </dependency>
        <dependency>
            <groupId>org.apache.flink</groupId>
            <artifactId>flink-table-common</artifactId>
            <version>1.12.0</version>
            <scope>compile</scope>
        </dependency>
        <dependency>
            <groupId>org.apache.hadoop</groupId>
            <artifactId>hadoop-common</artifactId>
            <version>3.3.0</version>
        </dependency>
        <dependency>
            <groupId>org.apache.hadoop</groupId>
            <artifactId>hadoop-client</artifactId>
            <version>3.3.0</version>
        </dependency>
        <dependency>
            <groupId>org.apache.hive</groupId>
            <artifactId>hive-jdbc</artifactId>
            <version>3.1.2</version>
        </dependency>
        <dependency>
            <groupId>org.apache.hive</groupId>
            <artifactId>hive-metastore</artifactId>
            <version>3.1.2</version>
        </dependency>
        <dependency>
            <groupId>org.apache.hive</groupId>
            <artifactId>hive-exec</artifactId>
            <version>3.1.2</version>
            <scope>compile</scope>
        </dependency>
        <dependency>
            <groupId>org.apache.flink</groupId>
            <artifactId>flink-table-api-java-bridge_2.11</artifactId>
            <version>1.12.0</version>
            <scope>compile</scope>
        </dependency>
        <dependency>
            <groupId>org.apache.thrift</groupId>
            <artifactId>libfb303</artifactId>
            <version>0.9.3</version>
            <type>pom</type>
        </dependency>
        <dependency>
            <groupId>com.fasterxml.jackson.core</groupId>
            <artifactId>jackson-databind</artifactId>
            <version>2.9.1</version>
        </dependency>
        <!-- https://mvnrepository.com/artifact/com.alibaba/fastjson -->
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>fastjson</artifactId>
            <version>1.2.75</version>
        </dependency>
    </dependencies>

三、创建执行环境

StreamExecutionEnvironment streamEnv = StreamExecutionEnvironment.getExecutionEnvironment();
streamEnv.setParallelism(1);
streamEnv.setStreamTimeCharacteristic(TimeCharacteristic.EventTime);
streamEnv.enableCheckpointing(60000);
​
EnvironmentSettings envSettings = EnvironmentSettings.newInstance().useBlinkPlanner().inStreamingMode().build();
StreamTableEnvironment tableEnv = StreamTableEnvironment.create(streamEnv, envSettings);
tableEnv.getConfig().getConfiguration().set(ExecutionCheckpointingOptions.CHECKPOINTING_MODE, CheckpointingMode.EXACTLY_ONCE);
tableEnv.getConfig().getConfiguration().set(ExecutionCheckpointingOptions.CHECKPOINTING_INTERVAL, Duration.ofMinutes(1));

四、注册hive catalog

注册hive catalog用于读写hive

String name = "hiveCatalog";      // Catalog名称,定义一个唯一的名称表示
String defaultDatabase = "test";  // 默认数据库名称
String hiveConfDir = "D:\\";  // hive-site.xml路径
String version = "3.1.2";       // Hive版本号
HiveCatalog hiveCatalog = new HiveCatalog(name, defaultDatabase, hiveConfDir,version);
tableEnv.registerCatalog(name, hiveCatalog);
tableEnv.useCatalog(name);

五、连接kafka数据源

Properties properties = new Properties();
properties.setProperty("bootstrap.servers", "localhost:9092");
properties.setProperty("group.id", "test");
//创建kafka cunsumer
FlinkKafkaConsumer<ObjectNode> flinkKafkaConsumer = new FlinkKafkaConsumer<ObjectNode>("topic", new JSONKeyValueDeserializationSchema(true), properties)
flinkKafkaConsumer.setStartFromEarliest();     // start from the earliest record possible
//将kafka cunsumer加入数据源
DataStream<String> stream = streamEnv.addSource(flinkKafkaConsumer);

六、业务相关代码

String[] fieldNames = {"id", "log", "op"};
TypeInformation[] types = {Types.STRING, Types.STRING, Types.STRING};
//以下为业务相关代码,不做详细展开
SingleOutputStreamOperator<Row> mapedStream= dataStreamSource.map(new GetIncDataMap(),new RowTypeInfo(types, fieldNames));
//flink流转换为表
tableEnv.createTemporaryView("kafkaRow", mapedStream);

七、执行具体sql

将kafka流表插入到hive中

tableEnv.getConfig().setSqlDialect(SqlDialect.HIVE);
tableEnv.executeSql("DROP TABLE IF EXISTS hivelogtab").print();
tableEnv.executeSql("CREATE TABLE hivelogtab ( id STRING,log STRING,op STRING)").print();
tableEnv.getConfig().setSqlDialect(SqlDialect.DEFAULT);
//        CloseableIterator<Row> result = tableEnv.sqlQuery("SELECT id,log,op FROM  kafkaRow").execute().collect();
//        while(result.hasNext()){
//            System.out.println(result.next());
//        }
TableResult tableResult = tableEnv.executeSql("INSERT INTO  hiveCatalog.test.hivelogtab SELECT id,log,op FROM  kafkaRow");        
streamEnv.execute("job");

八、测试

mysql源数据

schema

hive目标端同步的数据

schema

注:

由于hive是数据仓库,其本身为数据分析而生,不支持update、delete操作,但是在CDC场景中,不能保证源端数据库的操作全部为insert,因此可采用以下方式进行处理(参考美团数仓平台的架构与实践):

schema

图片源于网络,侵权删

TO DO :

schema信息中ddl语句的自动解析(包括源端与目标端的数据类型、关键字差异解析)​

在gzh "HEY DATA"后台回复"HIVE"后获得demo文件。

公众号

  • 6
    点赞
  • 52
    收藏
    觉得还不错? 一键收藏
  • 8
    评论
### 回答1: Apache Flink 是一个流处理框架,支持从 Apache Kafka 读取数据,并将其写入 Apache HiveFlinkKafkaHive 输入/输出接口可以方便地配置和使用,以实现从 KafkaHive数据流转。 ### 回答2: Flink是目前非常流行的分布式数据处理引擎,而Kafka则是高性能、高可靠的分布式消息队列系统,而Hive是一种基于Hadoop的数据仓库系统。那么如何将FlinkKafka读取数据,并将数据写入Hive中呢?下面介绍一下具体实现方式: 首先,需要在项目中导入FlinkKafka的依赖包,然后配置Kafka连接信息,如Kafka的地址、zookeeper地址、Topic名称以及消费组的名称等信息。然后,就可以通过Flink提供的Kafka Consumer API来读取Kafka中的数据。在代码中可以使用Flink DataStream API来进行数据转换、处理以及写入Hive等操作。 下面是一个FlinkKafka读取数据,然后将数据写入Hive的示例代码: ```java public class FlinkKafkaHiveDemo { public static void main(String[] args) throws Exception { StreamExecutionEnvironment env = StreamExecutionEnvironment.getExecutionEnvironment(); env.enableCheckpointing(5000); Properties properties = new Properties(); properties.setProperty("bootstrap.servers", "localhost:9092"); properties.setProperty("group.id", "test-consumer-group"); properties.setProperty("zookeeper.connect", "localhost:2181"); properties.setProperty("auto.offset.reset", "earliest"); properties.setProperty("enable.auto.commit", "false"); FlinkKafkaConsumer<String> consumer = new FlinkKafkaConsumer<>("test", new SimpleStringSchema(), properties); DataStream<String> stream = env.addSource(consumer); // 处理数据 DataStream<Tuple2<String, Integer>> result = stream .flatMap(new FlatMapFunction<String, Tuple2<String, Integer>>() { @Override public void flatMap(String s, Collector<Tuple2<String, Integer>> collector) throws Exception { String[] words = s.split("\\s+"); for (String word : words) { collector.collect(new Tuple2<>(word, 1)); } } }) .keyBy(0) .sum(1); // 将结果写入Hive final String dbName = "testDb"; final String tblName = "testTbl"; final String warehouseDir = "/user/hive/warehouse"; final String hiveConfDir = "/usr/local/hive/conf"; Configuration config = new Configuration(); config.set("hive.metastore.uris", "thrift://localhost:9083"); HiveConf hiveConf = new HiveConf(config, HiveConf.class); result.writeAsText("file:///home/user/result.txt"); result.addSink(new HiveSink<>(hiveConf, dbName, tblName, warehouseDir, new Tuple2RowConverter())); env.execute("Flink Kafka Hive Demo"); } } ``` 在代码中,我们使用FlinkKafkaConsumer来读取Kafka中名为test的Topic的数据,然后使用flatMap和sum对数据进行处理。接着,将结果写入Hive。在使用HiveSink对结果进行写入时,需要指定Hive相关的元数据信息,以及数据Hive中的存储路径等信息的具体实现方法。最后,在命令行中执行该代码即可。 总之,Flink读取Kafka并将数据写入Hive是非常常见且实用的一种方式,通过简单的配置和代码实现,可以实现对数据的高效处理和快速存储。 ### 回答3: Apache Flink作为一款实时大数据处理框架,支持读取来自Kafka数据并将其写入Hive,这也是Flink的常见应用场景之一。在介绍如何将数据Kafka写入Hive之前,有必要了解一下FlinkHive的相关知识。 Flink是一个开源的流处理框架,具有高吞吐、低延迟、容错性强等优点。它支持多种数据源,包括Kafka、HDFS、文件、Socket、JDBC等。同时,Flink也支持将数据写入多种数据存储系统,如Hive、HBase、Cassandra等。 Hive是一个开源的数据仓库系统,它可以在Hadoop上进行数据管理和查询。通过Hive,用户可以使用SQL语言对数据进行查询、汇总、分析等操作。Hive数据存储在HDFS上,支持多种文件格式,如ORC、Parquet、Avro等。 要将数据Kafka写入Hive,需要先创建一个Flink数据流,然后通过Flink提供的Kafka Consumer将数据读取数据流中。接着,使用Flink提供的HiveWriter将数据写入Hive表中。以下是具体步骤: 1. 创建Flink数据流:使用Flink提供的StreamExecutionEnvironment创建数据流,并为其指定数据源和数据存储方式。 2. 配置Kafka Consumer:使用Flink提供的Kafka Consumer将数据Kafka读取Flink数据流中。需要指定Kafka集群的地址、主题名称等参数。 3. 解析数据:在数据流中,每条数据可以是一个JSON对象、XML节点等格式,需要将其解析为可读取Hive表中的结构化数据,例如CSV格式。 4. 创建Hive表:在Hive中创建一个表,用于存储来自Kafka数据。需要指定表的结构和文件格式,例如CSV、Parquet等。 5. 配置HiveWriter:使用Flink提供的HiveWriter将数据写入Hive表中。需要指定Hive表的名称、文件格式、文件路径等参数。 6. 启动任务:将以上步骤整合到一个Flink任务中,并启动该任务,即可将来自Kafka数据写入Hive表中。 综上所述,Flink读取Kafka数据并将其写入Hive表的过程涉及到FlinkKafkaHive等多方面的知识,需要仔细地配置所有参数和细节,确保数据能够顺利地传输和存储。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 8
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值