1.概述

最近有同学留言咨询Kafka数据落地到Hive的一些问题,今天笔者将为大家来介绍一种除Flink流批一体以外的方式(流批一体下次再单独写一篇给大家分享)。

2.内容

首先,我们简单来描述一下数据场景,比如有这样一个数据场景,有一批实时流数据实时写入Kafka,然后需要对Topic中的数据进行每隔5分钟进行落地到Hive,进行每5分钟分区存储。流程图如下所示:

2.1 环境依赖

整个流程,需要依赖的组件有Kafka、Flink、Hadoop。由于Flink提交需要依赖Hadoop的计算资源和存储资源,所以Hadoop的YARN和HDFS均需要启动。各个组件版本如下:

组件 版本
Kafka 2.4.0
Flink 1.10.0
Hadoop 2.10.0

2.2 每分钟落地HDFS实现

Flink消费Kafka集群中的数据,需要依赖Flink包,依赖如下:

<dependency>
<groupId>org.apache.flink</groupId>
<artifactId>flink-connector-filesystem_2.12</artifactId>
<version>${flink.connector.version}</version>
</dependency>
<dependency>
<groupId>org.apache.flink</groupId>
<artifactId>flink-connector-kafka-0.11_2.12</artifactId>
<version>${flink.kafka.version}</version>
</dependency>
<dependency>
<groupId>org.apache.flink</groupId>
<artifactId>flink-streaming-java_2.12</artifactId>
<version>${flink.streaming.version}</version>
</dependency>

编写消费Topic的Flink代码,这里不对Topic中的数据做逻辑处理,在后面统一交给MapReduce来做数据预处理,直接消费并存储到HDFS上。代码如下:

public class Kafka2Hdfs {

    private static Logger LOG = LoggerFactory.getLogger(Kafka2Hdfs.class);

    public static void main(String[] args) {
if (args.length != 3) {
LOG.error("kafka(server01:9092), hdfs(hdfs://cluster01/data/), flink(parallelism=2) must be exist.");
return;
}
String bootStrapServer = args[0];
String hdfsPath = args[1];
int parallelism = Integer.parseInt(args[2]); StreamExecutionEnvironment env = StreamExecutionEnvironment.getExecutionEnvironment();
env.enableCheckpointing(5000);
env.setParallelism(parallelism);
env.setStreamTimeCharacteristic(TimeCharacteristic.EventTime); DataStream<String> transction = env.addSource(new FlinkKafkaConsumer010<>("test_bll_data", new SimpleStringSchema(), configByKafkaServer(bootStrapServer))); // Storage into hdfs
BucketingSink<String> sink = new BucketingSink<>(hdfsPath); sink.setBucketer(new JDateTimeBucketer<String>("HH-mm"));// 自定义存储到HDFS上的文件名,用小时和分钟来命名,方便后面算策略 sink.setBatchSize(1024 * 1024 * 4); // this is 5MB
sink.setBatchRolloverInterval(1000 * 30); // 30s producer a file into hdfs
transction.addSink(sink); env.execute("Kafka2Hdfs");
} private static Object configByKafkaServer(String bootStrapServer) {
Properties props = new Properties();
props.setProperty("bootstrap.servers", bootStrapServer);
props.setProperty("group.id", "test_bll_group");
props.put("enable.auto.commit", "true");
props.put("auto.commit.interval.ms", "1000");
props.put("key.deserializer", "org.apache.kafka.common.serialization.StringDeserializer");
props.put("value.deserializer", "org.apache.kafka.common.serialization.StringDeserializer");
return props;
} }

2.3 注意事项

  • 这里我们把时间窗口设置小一些,每30s做一次检查,如果该批次的时间窗口没有数据过来,就生成一个文件落地到HDFS上;
  • 另外,我们重写了DateTimeBucketer为JDateTimeBucketer,逻辑并不复杂,在原有的方法上加一个年-月-日/时-分的文件生成路径,例如在HDFS上的生成路径:xxxx/2020-12-26/00-00

2.4 数据预处理

这里,我们需要对落地到HDFS上的文件进行预处理,处理的逻辑是这样的。比如,现在是2020-12-26 14:00,那么我们需要将当天的13:55,13:56,13:57,13:58,13:59这最近5分钟的数据处理到一起,并加载到Hive的最近5分钟的一个分区里面去。那么,我们需要生成这样一个逻辑策略集合,用HH-mm作为key,与之最近的5个文件作为value,进行数据预处理合并。

实现代码如下:

public class DateRange {

    public static void main(String[] args) {
for (int i = 0; i < 24; i++) {
for (int j = 0; j < 60; j++) {
if (j % 5 == 0) {
if (j < 10) {
if (i < 10) {
if (i == 0 && j == 0) {
System.out.println("0" + i + "-0" + j + "=>23-59,23-58,23-57,23-56,23-55");
} else {
if (j == 0) {
String tmp = "";
for (int k = 1; k <= 5; k++) {
tmp += "0" + (i - 1) + "-" + (60 - k) + ",";
}
System.out.println("0" + i + "-0" + j + "=>" + tmp.substring(0, tmp.length() - 1));
} else {
String tmp = "";
for (int k = 1; k <= 5; k++) {
if (j - k < 10) {
tmp += "0" + i + "-0" + (j - k) + ",";
} else {
tmp += "0" + i + "-" + (j - k) + ",";
}
}
System.out.println("0" + i + "-0" + j + "=>" + tmp.substring(0, tmp.length() - 1));
}
}
} else {
if (j == 0) {
String tmp = "";
for (int k = 1; k <= 5; k++) {
if (i - 1 < 10) {
tmp += "0" + (i - 1) + "-" + (60 - k) + ",";
} else {
tmp += (i - 1) + "-" + (60 - k) + ",";
}
}
System.out.println(i + "-0" + j + "=>" + tmp.substring(0, tmp.length() - 1));
} else {
String tmp = "";
for (int k = 1; k <= 5; k++) {
if (j - k < 10) {
tmp += i + "-0" + (j - k) + ",";
} else {
tmp += i + "-" + (j - k) + ",";
}
}
System.out.println(i + "-0" + j + "=>" + tmp.substring(0, tmp.length() - 1));
}
}
} else {
if (i < 10) {
String tmp = "";
for (int k = 1; k <= 5; k++) {
if (j - k < 10) {
tmp += "0" + i + "-0" + (j - k) + ",";
} else {
tmp += "0" + i + "-" + (j - k) + ",";
}
}
System.out.println("0" + i + "-" + j + "=>" + tmp.substring(0, tmp.length() - 1));
} else {
String tmp = "";
for (int k = 1; k <= 5; k++) {
if (j - 1 < 10) {
tmp += i + "-0" + (j - k) + ",";
} else {
tmp += i + "-" + (j - k) + ",";
}
}
System.out.println(i + "-" + j + "=>" + tmp.substring(0, tmp.length() - 1));
}
}
}
}
}
} }

预览结果如下:

需要注意的是,如果发生了第二天00:00,那么我们需要用到前一天的00-00=>23-59,23-58,23-57,23-56,23-55这5个文件中的数据来做预处理。

2.5 数据加载

准备好数据后,我们可以使用Hive的load命令直接加载HDFS上预处理的文件,把数据加载到对应的表中,实现命令如下:

load data inpath '/cluster01/hive/hfile/data/min/2020-12-26/14-05/' overwrite into table jketable partition(day='2020-12-26-14-05')

这里,我们在执行命令时,可能文件不存在会导致加载出错。那我们在加载HDFS路径之前,先判断一下路径是否存在。

实现脚本如下所示:

hdfs dfs -ls /cluster01/hive/hfile/data/min/2020-12-26/14-05/ | wc -l > /tmp/hdfs_check_files.txt

hdfs_check_files=`cat /tmp/hdfs_check_files.txt`

# 判断HDFS上文件是否存在
if [ $hdfs_check_files -eq 0 ]
then
echo "Match file is null.Stop hive load script."
else
echo "Match file is exist.Start hive load script."
hive -e "load data inpath '/cluster01/hive/hfile/data/min/2020-12-26/14-05/' overwrite into table jketable partition(day='2020-12-26-14-05')"
fi

3.总结

整个流程为,先使用Flink消费存储在Kafka中的数据,按照每分钟进行存储,然后将具体需要聚合的时间段进行策略生成,比如每5分钟、10分钟、15分钟等等,可以在DateRange类中修改对应的策略逻辑。最后,再将预处理好的数据使用hive命令进行加载。整个过程,流程较多。如果我们使用Flink的流批一体特性,可以通过Flink直接建表,然后使用Flink消费Kafka中的数据后,直接分区落地到Hive表,这个就留到下次再给大家分享吧。

4.结束语

这篇博客就和大家分享到这里,如果大家在研究学习的过程当中有什么问题,可以加群进行讨论或发送邮件给我,我会尽我所能为您解答,与君共勉!

另外,博主出书了《Kafka并不难学》和《Hadoop大数据挖掘从入门到进阶实战》,喜欢的朋友或同学, 可以在公告栏那里点击购买链接购买博主的书进行学习,在此感谢大家的支持。关注下面公众号,根据提示,可免费获取书籍的教学视频。

Kafka数据每5分钟同步到Hive的更多相关文章

  1. 【转】美团 MySQL 数据实时同步到 Hive 的架构与实践

    文章转载自公众号  美团技术团队 , 作者 萌萌 背景 在数据仓库建模中,未经任何加工处理的原始业务层数据,我们称之为ODS(Operational Data Store)数据.在互联网企业中,常见的 ...

  2. hadoop生态系统学习之路(八)hbase与hive的数据同步以及hive与impala的数据同步

    在之前的博文中提到,hive的表数据是能够同步到impala中去的. 一般impala是提供实时查询操作的,像比較耗时的入库操作我们能够使用hive.然后再将数据同步到impala中.另外,我们也能够 ...

  3. Kafka数据如何同步至MaxCompute之实践讲解

    摘要:本次分享主要介绍Kafka产品的原理和使用方式,以及同步数据到MaxCompute的参数介绍.独享集成资源组与自定义资源组的使用背景和配置方式.Kafka同步数据到MaxCompute的开发到生 ...

  4. Gobblin采集kafka数据

    作者:Syn良子 出处:http://www.cnblogs.com/cssdongl 转载请注明出处 找时间记录一下利用Gobblin采集kafka数据的过程,话不多说,进入正题 一.Gobblin ...

  5. 漫游Kafka设计篇之主从同步

    Kafka允许topic的分区拥有若干副本,这个数量是可以配置的,你可以为每个topci配置副本的数量.Kafka会自动在每个个副本上备份数据,所以当一个节点down掉时数据依然是可用的. Kafka ...

  6. 工具篇-Spark-Streaming获取kafka数据的两种方式(转载)

    转载自:https://blog.csdn.net/weixin_41615494/article/details/7952173 一.基于Receiver的方式 原理 Receiver从Kafka中 ...

  7. 一文看懂大数据的技术生态Hadoop, hive,spark都有了[转]

    大数据本身是个很宽泛的概念,Hadoop生态圈(或者泛生态圈)基本上都是为了处理超过单机尺度的数据处理而诞生的.你可以把它比作一个厨房所以需要的各种工具.锅碗瓢盆,各有各的用处,互相之间又有重合.你可 ...

  8. 浅析大数据的技术生态圈(Hadoop,hive,spark)

    大数据本身是个很宽泛的概念,Hadoop生态圈(或者泛生态圈)基本上都是为了处理超过单机尺度的数据处理而诞生的.你可以把它比作一个厨房所以需要的各种工具.锅碗瓢盆,各有各的用处,互相之间又有重合.你可 ...

  9. Kafka数据安全性、运行原理、存储

    直接贴面试题: 怎么保证数据 kafka 里的数据安全? 答: 生产者数据的不丢失kafka 的 ack 机制: 在 kafka 发送数据的时候,每次发送消息都会有一个确认反馈机制,确保消息正常的能够 ...

随机推荐

  1. Java集合【8】-- ArrayList源码分析

    目录 1. ArrayList 1.1 ArrayList特点介绍 1.2 实现的接口和继承的类 2. 成员变量 3. 构造方法 4. 常用增删改查方法 添加元素 查询元素 更新元素 删除元素 5.自 ...

  2. 听说高手都用记事本写C语言代码?那你知道怎么编译运行吗?

    坊间传闻高手都喜欢用记事本写代码,那么问题来了,我们以C语言为例,如何用记事本编译运行呢?其实最简单的方式就是安装GCC编译器,在记事本编写C语言程序,然后再在命令行用GCC编译运行,下面我简单介绍一 ...

  3. 公平lock和非公平lock的区别

    可以看到区别在于,在lock时和tryAquire时,非公平锁不会去管队列中有没有线程在排队,直接尝试去获取锁,失败之后就和公平锁一样,乖乖去排队. 也就是说发生竞争的场景在于,尚未入队的线程之间和刚 ...

  4. 【微信开发】缓存的asscess_token过期

    开发中有遇到这样一个问题,我们一般会将从微信拿到的寿命2个小时的access_token缓存起来,业务里这个缓存的时间是90分钟, 90分钟之后缓存过期,会重新请求新的access_token使旧的a ...

  5. ubuntu配置网络和静态路由(界面配置形式)

    目录 网卡配置 静态ip配置 静态路由 外网ip配置(动态获取DHCP) 内网ip和静态路由配置 本文主要针对ubuntu18.0系统进行界面形式配置网络.并配置静态路由. 网卡配置 静态ip配置 打 ...

  6. 排序-InsertionSort 插入排序

    插入排序 の implementation 插入排序就像打赌的时候,比如双扣.抽牌的时候,一次拿一张牌,这张牌和之前的牌一张张比较.选择把这张牌插入什么位置,排好顺序的位置后打牌更顺.要不然得一个一个 ...

  7. Python_爬虫养殖专业户_00

    为什么学习爬虫? 当你在夜深人静,睡不着觉,想看一些更加睡不着觉的图片/视频时... 这是一句疑似玩笑话, 现实情况是, 每一天, 整个社会都积累了大量的数据, 在数据化的社会中,没有大批量的收集和探 ...

  8. 老猿学5G:多量纲计费与QoS的QCI、5QI、ARP、GBR和MBR

    ☞ ░ 前往老猿Python博文目录 ░ 一.多量纲计费 多量纲计费是与传统的计费模式相区别的一种计费模式,传统的计费基本上都是通过使用量.使用时长或包固定时长等方式计费,而多量纲计费是指在考虑以上方 ...

  9. 转:HTTP协议简介与在python中的使用详解

    1. 使用谷歌/火狐浏览器分析 在Web应用中,服务器把网页传给浏览器,实际上就是把网页的HTML代码发送给浏览器,让浏览器显示出来.而浏览器和服务器之间的传输协议是HTTP,所以: HTML是一种用 ...

  10. PyQt(Python+Qt)学习随笔:QListView的flow属性

    老猿Python博文目录 专栏:使用PyQt开发图形界面Python应用 老猿Python博客地址 QListView的flow属性用于控制视图中的数据排列方向,其类型为枚举类型QListView.F ...