2020-12-26

博客园Logo
首页
新闻
博问
专区
闪存
班级

代码改变世界
搜索
注册
登录
返回主页 哥不是小萝莉
博客园 首页 新随笔 联系 订阅 管理随笔 - 145 文章 - 0 评论 - 425
Kafka数据每5分钟同步到Hive
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包,依赖如下:

复制代码

org.apache.flink
flink-connector-filesystem_2.12
f l i n k . c o n n e c t o r . v e r s i o n < / v e r s i o n > < / d e p e n d e n c y > < d e p e n d e n c y > < g r o u p I d > o r g . a p a c h e . f l i n k < / g r o u p I d > < a r t i f a c t I d > f l i n k − c o n n e c t o r − k a f k a − 0.1 1 2 . 12 < / a r t i f a c t I d > < v e r s i o n > {flink.connector.version}</version> </dependency> <dependency> <groupId>org.apache.flink</groupId> <artifactId>flink-connector-kafka-0.11_2.12</artifactId> <version> flink.connector.version</version></dependency><dependency><groupId>org.apache.flink</groupId><artifactId>flinkconnectorkafka0.112.12</artifactId><version>{flink.kafka.version}


org.apache.flink
flink-streaming-java_2.12
${flink.streaming.version}

复制代码
编写消费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大数据挖掘从入门到进阶实战》,喜欢的朋友或同学, 可以在公告栏那里点击购买链接购买博主的书进行学习,在此感谢大家的支持。关注下面公众号,根据提示,可免费获取书籍的教学视频。

联系方式:
邮箱:smartloli.org@gmail.com
Twitter:https://twitter.com/smartloli
QQ群(Hadoop - 交流社区1):424769183
QQ群(Kafka并不难学): 825943084
温馨提示:请大家加群的时候写上加群理由(姓名+公司/学校),方便管理员审核,谢谢!
热爱生活,享受编程,与君共勉!

公众号:

作者:哥不是小萝莉 [关于我][犒赏]
出处:http://www.cnblogs.com/smartloli/
转载请注明出处,谢谢合作!
分类: kafka, hadoop
标签: 每5分钟落地到hive, kafka, hive, flink
好文要顶 关注我 收藏该文
哥不是小萝莉
关注 - 0
粉丝 - 778
+加关注
1 0
« 上一篇: Kafka分布式查询引擎
posted @ 2020-12-26 17:03 哥不是小萝莉 阅读(39) 评论(0) 编辑 收藏
刷新评论刷新页面返回顶部
登录后才能发表评论,立即 登录 或 注册, 访问 网站首页
写给园友们的一封求助信
【推荐】News: 大型组态、工控、仿真、CADGIS 50万行VC++源码免费下载
【推荐】有你助力,更好为你——博客园用户消费观调查,附带小惊喜!
【推荐】博客园x丝芙兰-圣诞特别活动:圣诞选礼,美力送递
【推荐】了不起的开发者,挡不住的华为,园子里的品牌专区
【福利】AWS携手博客园为开发者送免费套餐+50元京东E卡
【推荐】未知数的距离,毫秒间的传递,声网与你实时互动
【推荐】新一代 NoSQL 数据库,Aerospike专区新鲜入驻

相关博文:
· kafka?kafaka!kafka…
· kafka
· kafka
· Kafka基础——Kafka架构
· HiveFunctions
» 更多推荐…

最新 IT 新闻:
· 熬过2020,我的公司还活着
· 一夜之间,两家A股网游上市公司实控人出大事了!
· 苹果造车,到底有没有戏?
· 玩了10小时《赛博朋克2077》 我觉得很失望
· 一文读懂2020年大厂如何调整组织架构
» 更多新闻…
Kafka并不难学
Kafka并不难学
京东自营 当当自营 亚马逊自营
Hadoop大数据挖掘从入门到进阶实战
Hadoop大数据挖掘从入门到进阶实战
京东自营 当当自营 亚马逊自营
昵称: 哥不是小萝莉
园龄: 6年4个月
粉丝: 778
关注: 0
+加关注
< 2020年12月 >
日 一 二 三 四 五 六
29 30 1 2 3 4 5
6 7 8 9 10 11 12
13 14 15 16 17 18 19
20 21 22 23 24 25 26
27 28 29 30 31 1 2
3 4 5 6 7 8 9
搜索

找找看

谷歌搜索
最新随笔
1.Kafka数据每5分钟同步到Hive
2.Kafka分布式查询引擎
3.协同过滤在推荐系统中的应用
4.Kafka消费与心跳机制
5.如何构建一个生产环境的推荐系统
6.Kafka Eagle V2.0.0新版预览
7.基于用户的协同过滤来构建推荐系统
8.Kafka SSL安装与配置
9.如何构建推荐系统
10.Flink消费Kafka到HDFS实现及详解
积分与排名
积分 - 370149
排名 - 1194
随笔分类 (275)
elasticsearch(5)
git(2)
hadoop(116)
java(71)
jenkins(1)
kafka(54)
MongoDB(2)
other(1)
python(6)
spark(6)
storm(9)
thrift(2)
随笔档案 (145)
2020年12月(1)
2020年11月(1)
2020年10月(1)
2020年9月(1)
2020年8月(1)
2020年7月(1)
2020年6月(1)
2020年5月(1)
2020年4月(1)
2020年3月(1)
2020年2月(1)
2020年1月(1)
2019年12月(1)
2019年11月(1)
2019年10月(1)
更多
最新评论

  1. Re:Kafka Eagle V1.3.4更新预览
    @13小哪吒 上述异常,是没有获取到你的Kafka节点数 另外,你的Kafka版本多少?下面这两个属性需要注意: (1) 0.10.2之后的新版本 cluster1.kafka.eagle.offse…
    –哥不是小萝莉
  2. Re:Kafka Eagle V1.3.4更新预览
    [2020-12-22 17:18:00] KafkaServiceImpl.Thread-943 - ERROR - Get kafka old version logsize & parse ha…
    –13小哪吒
  3. Re:Kafka Eagle V1.3.4更新预览
    @哥不是小萝莉 能请教您个问题吗,我在搭建kafka eagle的时候遇到了一些问题。想请您帮忙解答下。报错日志如下
    –13小哪吒
  4. Re:Kafka分布式查询引擎
    楼主改源代码加索引成功了吗?之前我们也有类似的需求,也有过同样的想法
    –nchuxyz
  5. Re:Kafka分布式查询引擎
    受教了。
    –萧莫
    阅读排行榜
  6. Hive性能优化(73894)
  7. 高可用Hadoop平台-Hue In Hadoop(45527)
  8. 高可用的MongoDB集群(44444)
  9. Kafka 消息监控 - Kafka Eagle(39987)
  10. Kafka实战-简单示例(33366)
    评论排行榜
  11. Kafka 消息监控 - Kafka Eagle(69)
  12. Kafka Eagle安装详情及问题解答(19)
  13. 配置高可用的Hadoop平台(17)
  14. Kafka Eagle 源码解读(16)
  15. Kafka Eagle V2.0.0新版预览(11)
    推荐排行榜
  16. Hive性能优化(18)
  17. 网站日志统计案例分析与实现(18)
  18. 高可用的MongoDB集群(13)
  19. 配置高可用的Hadoop平台(13)
  20. 如何构建推荐系统(12)
    Copyright © 2020 哥不是小萝莉
    Powered by .NET 5.0.1-servicing.20575.16 on Kubernetes
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值