项目概览


flink 实时数据仓库 维度表 flink实时数仓项目_flink

项目主要通过实时数仓的搭建来完成对Flink的进一步掌握和学习,Flink代码的编写使用的是Java,其中会涉及到Flink的很多知识点,FlinkCDC,FlinkSQL,开船,富函数等,用来学习Flink顺便过一下数仓还是很可以的。根据FlinkForward2021中的一些动态,FlinkSQL化已经势不可挡,流式数仓StreamHouse也开始慢慢推进。

在这里实时数仓主要是为了提高数据的复用性,看下图,当有大量的中间结果

被使用的时候,就充分体现出来了是实时数仓的必要性,节省很多次重复的计算,提交实时计算的时效性。

flink 实时数据仓库 维度表 flink实时数仓项目_flink_02


说到数仓,离不开数仓分层,基于电商的实时数仓的分层如下:

ods:原始数据,存储业务数据和日志数据

dwd:根据数据对象为单位进行分流,如订单,页面访问

dim:维度数据

dwm:对部分数据对象进一步加工,和维表进行关联,形成宽表,如独立访问,跳出行为

dws:根据某个主题将多个事实数据轻度聚合,形成主题宽表

ads:根据数据进行可视化筛选聚合

实时需求

主要分为:日常统计报表或分析图模块,实时数据监控大屏,数据预警或提示,实时推荐系统。

项目架构分析

flink 实时数据仓库 维度表 flink实时数仓项目_数据_03

日志数据采集

flink 实时数据仓库 维度表 flink实时数仓项目_数据_04


这部分代码已经提供,请访问:https://gitee.com/he_wen_qi/flink-real-time-data-project 值得注意的是:application.properties中指定kafka代理地址:

spring.kafka.bootstrap-servers=master:9092

日志落盘并写入kafka

@RequestMapping("applog")
 public String getLogger(@RequestParam("param") String jsonStr) {
//日志落盘
log.info(jsonStr);
//写入kafka
kafkaTemplate.send("ods_base_log",jsonStr);
return "success";

另外使用nginx代理来做负载均衡,避免单台服务器压力过大

# 负载均衡
 upstream logcluster{
 server master:8081 weight=1;
 server slave:8081 weight=1;
 server slave1:8081 weight=1;
 }
 location / {
 #root html;
 #index index.html index.htm;
 # 代理的服务器集群 命名随意, 但是不能出现下划线
 proxy_pass http://logcluster;
 proxy_connect_timeout 10;
 }

业务数据采集

这里采用FlinkCDC进行采集
在之前的一篇文章中,已经提到过关于CDC以及FlinkCDC。
FlinkCDC代码实现:

//1.获取执行环境
        StreamExecutionEnvironment env = StreamExecutionEnvironment.getExecutionEnvironment();
        env.setParallelism(1);

        //2.通过FlinkCDC构建SourceFunction并读取数据
        DebeziumSourceFunction<String> sourceFunction = MySQLSource.<String>builder()
                .hostname("master")
                .port(3306)
                .username("root")
                .password("000000")
                .databaseList("mall2021")
                .deserializer(new CustomerDeserialization())
                .startupOptions(StartupOptions.latest())
//                .startupOptions(StartupOptions.initial())
                .build();
        DataStreamSource<String> streamSource = env.addSource(sourceFunction);

        //3.打印数据并将数据写入Kafka
        streamSource.print();
        String sinkTopic = "ods_base_db";
        streamSource.addSink(MyKafkaUtil.getKafkaProducer(sinkTopic));

        //4.启动任务
        env.execute("FlinkCDC");

将kafka代码进行封装:

public class MyKafkaUtil {
 private static String KAFKA_SERVER =
"master:9092,slave:9092,slave1:9092";
 private static Properties properties = new Properties();
 static {
 properties.setProperty("bootstrap.servers", KAFKA_SERVER);
 }
 public static FlinkKafkaProducer<String> getKafkaSink(String topic) {
 return new FlinkKafkaProducer<String>(topic, new SimpleStringSchema(), properties);
 }
}