vertx源码_实时数仓 | Flink实时维表join方法总结(附项目源码)

本文介绍了在实时数仓中处理缓慢变化维度的问题,提出了四种解决方案:直接查库定时更新、异步IO、Broadcast方式和异步IO结合Cache。详细探讨了每种方法的适用场景,并提供了部分代码示例。
摘要由CSDN通过智能技术生成

98e60e1580813766e7a6a6b44aa3cd33.gif

271f4180d36e4c205b6f9f429b257970.png

分享嘉宾:中国好胖子

编辑整理:柠檬妹

出品平台:数据仓库与Python大数据

目录

  1. 1、ETL背景
  2. 2、解决方案

    1. 2.1 直接查库定时更新

    2. 2.2 异步IO

    3. 2.3 Broadcast的方式

    4. 2.4 异步io结合Cache

  3. 3、完整源码

正文

Tips:推荐收藏,PC端观看效果更佳哦

1、ETL背景

在我们实时数仓日常工作中,经常会有一些实时的需求,这些需求往往都是一些拉宽的需求。为了给实时数仓来进行OLAP对来进行Ad-hoc查询,但是我们工作中一些维度表的数据是会发生变化的,可能是缓慢变化维度。那么这个时候就需要进行flink连接其他数据源来进行查询。那么这个时候我们肯定可以想到就是来一条查一次,这个是肯定可以做到的。

但是在大数据场景下,我们是不是会觉得有点慢呢?

我们是否有更好的解决方案,就像我写代码的时候 有时候就会思考有没有更好的解决方案。但是针对于要进行交付给用户,所以我们并没有那么多的时间进行思考来进行,因为产品一直都在催你哦。那么我们就来看看有几种解决方案:

a2c40fcf6386f04df040fd018e87e40d.png上图 是一个实时架构图。当然我们公司已经引入了clickhouse 实时数仓这些已经不是我们所追求的了,但是并不妨碍我们的需求。下面我们就来看一下数据。

{"dt":"2019-11-19 20:33:39","countryCode":"TW","data": [{"type":"s1","score":0.8,"level":"D"},{"type":"s2","score":0.1,"level":"B"}]} 
{"dt":"2019-11-19 20:33:41","countryCode":"KW","data": [{"type":"s2","score":0.2,"level":"A"},{"type":"s1","score":0.2,"level":"D"}]}
{"dt":"2019-11-19 20:33:43","countryCode":"HK","data": [{"type":"s5","score":0.5,"level":"C"},{"type":"s2","score":0.8,"level":"B"}]}
{"dt":"2019-11-19 20:33:39","countryCode":"TW","data": [{"type":"s1","score":0.8,"level":"D"},{"type":"s2","score":0.1,"level":"B"}]}

当然之上 是我们的模拟数据,接下来我们看看 业务人员需要什么数据

"dt":"2019-11-19 20:33:39","countryCode":"AREA_CT","type":"s1","score":0.8,"level":"D"

"dt":"2019-11-19 20:33:39","countryCode":"AREA_CT","type":"s2","score":0.1,"level":"B"

那么这个时候我们可以发现了,其实就是把国家 换成大区,这样入仓之后可以进行 大区的olap实时的一些分析。例如实时的绩效考核等,还有一些营销活动等。我们就不细细考量了,因为毕竟都是假数据。

那么我们看到原始数据和结果数据,我们发现,是进行了拆解,例如 一条记录中带有多个 type 也就是直播平台,但是结果数据拆成了两个,这个不是udtf吗?

同时将国家编码转化为大区编码,那么我们这时候假定大区编码会有变化,因为组织的重构问题,或者组织的架构演进等。

那么我们思考一下 有几种解决方案呢?

2、解决方案

2.1 直接查库定时更新

温馨提示:手机端左右滑动即可查看完整代码哦

 static class SimpleFlatMapFunction extends RichFlatMapFunction<String,OutData>{
    


private transient ConcurrentHashMap<String, String> hashMap = null;


@Override
public void open(Configuration parameters) throws Exception {
super.open(parameters);
Jedis jedisCluster = RedisFactory.getJedisCluster();

ScanResult<Map.Entry<String, String>> areas = jedisCluster.hscan("areas", "0");
List<Map.Entry<String, String>> result = areas.getResult();
System.out.println("更新缓存");

hashMap = new ConcurrentHashMap<>();
for (Map.Entry<String, String> stringStringEntry : result) {
String key = stringStringEntry.getKey();
String[] split = stringStringEntry.getValue().split(",");
for (String s : split) {
hashMap.put(s, key);
}
}
jedisCluster.close();
ScheduledExecutorService scheduledExecutorService = Executors.newScheduledThreadPool(1);
scheduledExecutorService.scheduleAtFixedRate(new Runnable() {
@Override
public void run() {
System.out.println("更新缓存");
Jedis jedisCluster = RedisFactory.getJedisCluster();

ScanResult<Map.Entry<String, String>> areas = jedisCluster.hscan("areas", "0");
List<Map.Entry<String, String>> result = areas.getResult();
hashMap = new ConcurrentHashMap<>();
for (Map.Entry<String, String> stringStringEntry : result) {
String key = stringStringEntry.getKey();
String[] split = stringStringEntry.getValue().split(",");
for (String s : split) {
hashMap.put(s, key);
}
}
jedisCluster.close();
}
}, 0, 3, TimeUnit.SECONDS);

}

@Override
public void flatMap(String s, Collector<OutData> collector) throws Exception {
OriginData originData = JSONObject.parseObject(s, OriginData.class);
String countryCode = originData.countryCode;
ArrayList<Data> data = originData.data;
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值