Flink ETL 实现数据清洗 

  

 一:需求(针对算法产生的日志数据进行清洗拆分)

  1. 算法产生的日志数据是嵌套json格式,需要拆分

  2.针对算法中的国家字段进行大区转换

  3.最后把不同类型的日志数据分别进行储存

二:整体架构 

      这里演示处理从rabbitmq来的数据 进行数据处理 然后发送到rabbitmq                            

 自定义redistSource flink没有redis的source

package com.yw.source;

import org.apache.flink.streaming.api.functions.source.SourceFunction;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import redis.clients.jedis.Jedis;
import redis.clients.jedis.exceptions.JedisConnectionException; import java.util.HashMap;
import java.util.Map; /**
* redis中进行数据初始化
* <p>
* 在reids中保存国家和大区关系
* hset areas AREA_IN IN
* hset areas AREA_US US
* hset areas AREA_CT TW,HK
* hset areas AREA_AR PK,KW,SA
*
*
* @Auther: YW
* @Date: 2019/6/15 10:23
* @Description:
*/
public class MyRedisSource implements SourceFunction<HashMap<String, String>> {
private final Logger LOG = LoggerFactory.getLogger(MyRedisSource.class); private boolean isRuning = true;
private Jedis jedis = null;
private final long SLEEP = 60000;
private final long expire = 60; @Override
public void run(SourceContext<HashMap<String, String>> ctx) throws Exception {
this.jedis = new Jedis("localhost", 6397);
// 存储国家和地区关系
HashMap<String, String> map = new HashMap<>();
while (isRuning) {
try {
map.clear(); // 老数据清除
Map<String, String> areas = jedis.hgetAll("areas");
for (Map.Entry<String, String> entry : areas.entrySet()) {
String key = entry.getKey();
String value = entry.getValue();
String[] splits = value.split(",");
for (String split : splits) {
map.put(split, key);
}
}
if (map.size() > 0) {
// map >0 数据发送出去
ctx.collect(map);
}else {
LOG.warn("获取数据为空!");
}
// 歇6秒
Thread.sleep(SLEEP);
} catch (JedisConnectionException e) {
LOG.error("redis连接异常 重新连接",e.getCause());
// 如果连接异常 重新连接
jedis = new Jedis("localhost", 6397);
}catch (Exception e){
LOG.error("redis Source其他异常",e.getCause());
} }
} @Override
public void cancel() {
isRuning = false;
while (jedis != null) {
jedis.close();
}
}
}
DataClean数据处理
package com.yw;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.rabbitmq.client.AMQP;
import com.yw.source.MyRedisSource;
import org.apache.flink.streaming.api.CheckpointingMode;
import org.apache.flink.streaming.api.datastream.DataStream;
import org.apache.flink.streaming.api.datastream.DataStreamSource;
import org.apache.flink.streaming.api.environment.CheckpointConfig;
import org.apache.flink.streaming.api.environment.StreamExecutionEnvironment;
import org.apache.flink.streaming.api.functions.co.CoFlatMapFunction;
import org.apache.flink.streaming.connectors.rabbitmq.RMQSink;
import org.apache.flink.streaming.connectors.rabbitmq.RMQSinkPublishOptions;
import org.apache.flink.streaming.connectors.rabbitmq.RMQSource;
import org.apache.flink.streaming.connectors.rabbitmq.common.RMQConnectionConfig;
import org.apache.flink.streaming.util.serialization.SimpleStringSchema;
import org.apache.flink.util.Collector; import java.util.HashMap; /**
* @Auther: YW
* @Date: 2019/6/15 10:09
* @Description:
*/
public class DataClean {
// 队列名
public final static String QUEUE_NAME = "two.aa.in"; public static void main(String[] args) throws Exception {
// 获取环境
StreamExecutionEnvironment env = StreamExecutionEnvironment.getExecutionEnvironment();
// 一分钟 checkpoint
env.enableCheckpointing(60000);
env.getCheckpointConfig().setCheckpointingMode(CheckpointingMode.EXACTLY_ONCE);
env.getCheckpointConfig().setMinPauseBetweenCheckpoints(30000); // enableCheckpointing最小间隔时间(一半)
env.getCheckpointConfig().setCheckpointTimeout(10000);// 超时时间
env.getCheckpointConfig().setMaxConcurrentCheckpoints(1);
env.getCheckpointConfig().enableExternalizedCheckpoints(CheckpointConfig.ExternalizedCheckpointCleanup.RETAIN_ON_CANCELLATION); final RMQConnectionConfig rmqConf = new RMQConnectionConfig.Builder().setHost("127.0.0.1").setPort(5672).setVirtualHost("/").setUserName("guest").setPassword("guest").build();
// 获取mq数据
DataStream<String> data1 = env.addSource(new RMQSource<String>(rmqConf, QUEUE_NAME, false, new SimpleStringSchema())).setParallelism(1);
//{"dt":"2019-06-10","countryCode":"US","data":[{"type":"s1","score":0.3,"level":"A"},{"type":"s2","score":0.1,"level":"B"},{"type":"s3","score":0.2,"level":"C"}]}
DataStreamSource<HashMap<String, String>> mapData = env.addSource(new MyRedisSource());
// connect可以连接两个流
DataStream<String> streamOperator = data1.connect(mapData).flatMap(new CoFlatMapFunction<String, HashMap<String, String>, String>() {
// 保存 redis返回数据 国家和大区的映射关系
private HashMap<String, String> allMap = new HashMap<String, String>(); // flatMap1 处理rabbitmq的数据
@Override
public void flatMap1(String value, Collector<String> out) throws Exception {
JSONObject jsonObject = JSONObject.parseObject(value);
String countryCode = jsonObject.getString("countryCode");
String dt = jsonObject.getString("dt");
// 获取大区
String area = allMap.get(countryCode);
JSONArray jsonArray = jsonObject.getJSONArray("data");
for (int i = 0; i < jsonArray.size(); i++) {
JSONObject jsonObject1 = jsonArray.getJSONObject(i);
jsonObject1.put("area", area);
jsonObject1.put("dt", dt);
out.collect(jsonObject1.toJSONString());
}
} // 处理redis的返回的map类型的数据
@Override
public void flatMap2(HashMap<String, String> value, Collector<String> out) throws Exception {
this.allMap = value;
}
});
streamOperator.addSink(new RMQSink<String>(rmqConf, new SimpleStringSchema(), new RMQSinkPublishOptions<String>() {
@Override
public String computeRoutingKey(String s) {
return "CC";
} @Override
public AMQP.BasicProperties computeProperties(String s) {
return null;
} @Override
public String computeExchange(String s) {
return "test.flink.output";
}
}));
data1.print();
env.execute("etl");
}
}

rabbitmq 模拟数据

package com.yw;

import com.rabbitmq.client.Channel;
import com.rabbitmq.client.Connection;
import com.rabbitmq.client.ConnectionFactory; import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Random; /**
* @Auther: YW
* @Date: 2019/6/5 14:57
* @Description:
*/
public class RabbitMQProducerUtil {
public final static String QUEUE_NAME = "two.aa.in"; public static void main(String[] args) throws Exception {
//创建连接工厂
ConnectionFactory factory = new ConnectionFactory(); //设置RabbitMQ相关信息
factory.setHost("127.0.0.1");
factory.setUsername("guest");
factory.setPassword("guest");
factory.setVirtualHost("/");
factory.setPort(5672); //创建一个新的连接
Connection connection = factory.newConnection();
//创建一个通道
Channel channel = connection.createChannel();
// 声明一个队列
// channel.queueDeclare(QUEUE_NAME, false, false, false, null);
//发送消息到队列中
String message = "{\"dt\":\""+getCurrentTime()+"\",\"countryCode\":\""+getCountryCode()+"\"," +
"{\"type\":\""+getType()+"\",\"score\":"+getScore()+"\"level\":\""+getLevel()+"\"}," +
"{\"type\":\""+getType()+"\",\"score\":"+getScore()+"\"level\":\""+getLevel()+"\"}," +
"{\"type\":\""+getType()+"\",\"score\":"+getScore()+"\"level\":\""+getLevel()+"\"}]}"; //我们这里演示发送一千条数据
for (int i = 0; i < 20; i++) {
channel.basicPublish("", QUEUE_NAME, null, (message + i).getBytes("UTF-8"));
System.out.println("Producer Send +'" + message);
} //关闭通道和连接
channel.close();
connection.close();
} public static String getCurrentTime() {
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
return sdf.format(new Date());
} public static String getCountryCode() {
String[] types={"US","TN","HK","PK","KW","SA","IN"};
Random random = new Random();
int i = random.nextInt(types.length);
return types[i];
} public static String getType() {
String[] types={"s1","s2","s3","s4","s5"};
Random random = new Random();
int i = random.nextInt(types.length);
return types[i];
} public static String getScore() {
String[] types={"0.1","0.2","0.3","0.4","0.5"};
Random random = new Random();
int i = random.nextInt(types.length);
return types[i];
}
public static String getLevel() {
String[] types={"A","B","C","D","E"};
Random random = new Random();
int i = random.nextInt(types.length);
return types[i];
}
}

redis 初始化数据

* hset areas AREA_IN IN
* hset areas AREA_US US
* hset areas AREA_CT TW,HK
* hset areas AREA_AR PK,KW,SA

------------最后运行DataClean------------

flink ETL数据处理的更多相关文章

  1. Spark与Flink大数据处理引擎对比分析!

    大数据技术正飞速地发展着,催生出一代又一代快速便捷的大数据处理引擎,无论是Hadoop.Storm,还是后来的Spark.Flink.然而,毕竟没有哪一个框架可以完全支持所有的应用场景,也就说明不可能 ...

  2. 基于docker构建flink大数据处理平台

    https://www.cnblogs.com/1ssqq1lxr/p/10417005.html 由于公司业务需求,需要搭建一套实时处理数据平台,基于多方面调研选择了Flink. 初始化Swarm环 ...

  3. 基于Broadcast 状态的Flink Etl Demo

    接上文: [翻译]The Broadcast State Pattern(广播状态) 最近尝试了一下Flink 的 Broadcase 功能,在Etl,流表关联场景非常适用:一个流数据量大,一个流数据 ...

  4. Flink学习笔记-新一代Flink计算引擎

    说明:本文为<Flink大数据项目实战>学习笔记,想通过视频系统学习Flink这个最火爆的大数据计算框架的同学,推荐学习课程: Flink大数据项目实战:http://t.cn/EJtKh ...

  5. Flink入门介绍

    什么是Flink Apache Flink是一个分布式大数据处理引擎,可以对有限数据流和无限数据流进行有状态计算.可部署在各种集群环境,对各种大小的数据规模进行快速计算. Flink特性 支持高吞吐. ...

  6. 深度介绍Flink在字节跳动数据流的实践

    本文是字节跳动数据平台开发套件团队在1月9日Flink Forward Asia 2021: Flink Forward 峰会上的演讲分享,将着重分享Flink在字节跳动数据流的实践. 字节跳动数据流 ...

  7. 带你玩转Flink流批一体分布式实时处理引擎

    摘要:Apache Flink是为分布式.高性能的流处理应用程序打造的开源流处理框架. 本文分享自华为云社区<[云驻共创]手把手教你玩转Flink流批一体分布式实时处理引擎>,作者: 萌兔 ...

  8. Flink基础概念入门

    Flink 概述 什么是 Flink Apache Apache Flink 是一个开源的流处理框架,应用于分布式.高性能.高可用的数据流应用程序.可以处理有限数据流和无限数据,即能够处理有边界和无边 ...

  9. ETL的经验总结

    ETL的考虑        做数据仓库系统,ETL是关键的一环.说大了,ETL是数据整合解决方案,说小了,就是倒数据的工具.回忆一下工作这么些年来,处理数据迁移.转换的工作倒还真的不少.但是那些工作基 ...

随机推荐

  1. Log4net 控制台打印日志(二)

    1.创建控制台程序 2.用NuGet添加log4net引用 3.添加应用程序配置文件:App.config 4.添加配置信息: <?xml version="1.0" enc ...

  2. Linux上使用Windows软件

    小书匠 安装完成后,甚至可以在linux上进行视频会议,整个过程分两个步骤: 1.安装deepin-wine 这个步骤看github,Jactor Sue这位老哥弄好了,在这: Deepin-Apps ...

  3. 计蒜客 38228. Max answer-线段树维护单调栈(The Preliminary Contest for ICPC China Nanchang National Invitational I. Max answer 南昌邀请赛网络赛) 2019ICPC南昌邀请赛网络赛

    Max answer Alice has a magic array. She suggests that the value of a interval is equal to the sum of ...

  4. python计算1~2008中0和1的个数

    计算1~2008中所有自然数中1和0的个数总数. 通过自然数的大小划分区间,将自然数每位上的数载入列表,循环计数. list = [] onecount = 0 zerocount = 0 for i ...

  5. Git创建与合并分支,撤销修改

    git回滚到指定版本并推送到远程分支(撤销已提交的修改,并已push) git reset --hard <commit ID号> git push -f git回滚到上一个版本并推送到远 ...

  6. python3.6安装 zipimport.ZipImportError: can't decompress data; zlib not available【转】

    python3.6.3 安装: .tgz cd Python- ./configure make make altinstall `make altinstall` , 报错: zipimport.Z ...

  7. 工具系列 | VScode Remote 远程开发与调试(告别SSH)

    简介 最近VScode发布了远程编程与调试的插件Remote Development,使用这个插件可以在很多情况下代替vim直接远程修改与调试服务器上的代码,同时具备代码高亮与补全功能,就和在本地使用 ...

  8. Redis常见问题及解决方案

    在Redis的运维使用过程中你遇到过那些问题,又是如何解决的呢?本文收集了一些Redis的常见问题以及解决方案,与大家一同探讨. 码字不易,欢迎大家转载,烦请注明出处:谢谢配合 你的Redis有big ...

  9. java使用ssh连接Linux并执行命令

     方式1:通过设置账号密码和链接地址 maven pom.xml配置: <dependency>         <groupId>com.jcraft</groupId ...

  10. CNeo编程语言概述

    C语言诞生于1970年,当时在AT&T实验室由Dennis Ritchie主导开发的.据说当时仅用了一周的时间就做好了C语言编译器,所以尽管C语言从90年正式纳入ISO标准委员会,其编号为IS ...