文章目录
一 DWS层与DWM层的设计
1 设计思路
之前通过分流等手段,把数据分拆成了独立的kafka topic。那么接下来如何处理数据,就要思考一下到底要通过实时计算出哪些指标项。
因为实时计算与离线不同,实时计算的开发和运维成本都是非常高的,要结合实际情况考虑是否有必要像离线数仓一样,建一个大而全的中间层。
如果没有必要大而全,这时候就需要大体规划一下要实时计算出的指标需求了。把这些指标以主题宽表的形式输出,就是DWS层。
2 DWS层需求分析
统计主题 | 需求指标 | 输出方式 | 计算来源 | 来源层级 |
---|---|---|---|---|
访客 | pv | 可视化大屏 | page_log直接可求 | dwd |
uv | 可视化大屏 | 需要用page_log过滤去重 | dwm | |
跳出明细 | 可视化大屏 | 需要通过page_log行为判断 | dwm | |
进入页面数 | 可视化大屏 | 需要识别开始访问标识 | dwd | |
连续访问时长 | 可视化大屏 | page_log直接可求 | dwd | |
商品 | 点击 | 多维分析 | page_log直接可求 | dwd |
收藏 | 多维分析 | 收藏表 | dwd | |
加入购物车 | 多维分析 | 购物车表 | dwd | |
下单 | 可视化大屏 | 订单宽表 | dwm | |
支付 | 多维分析 | 支付宽表 | dwm | |
退款 | 多维分析 | 退款表 | dwd | |
评论 | 多维分析 | 评论表 | dwd | |
地区 | pv | 多维分析 | page_log直接可求 | dwd |
uv | 多维分析 | 需要用page_log过滤去重 | dwm | |
下单 | 可视化大屏 | 订单宽表 | dwm | |
关键词 | 搜索关键词 | 可视化大屏 | 页面访问日志 直接可求 | dwd |
点击商品关键词 | 可视化大屏 | 商品主题下单再次聚合 | dws | |
下单商品关键词 | 可视化大屏 | 商品主题下单再次聚合 | dws |
当然实际需求还会有更多,这里主要以为可视化大屏为目的进行实时计算的处理。
DWM层的定位是主要服务于DWS,因为部分需求直接从DWD层到DWS层中间会有一定的计算量,而且这部分计算的结果很有可能被多个DWS层主题复用,所以部分DWD层会形成一层DWM,这里涉及业务主要包括:访问UV计算、 跳出明细计算、订单宽表、支付宽表。
二 DWM层-UV计算
1 需求分析与思路
UV,全称是Unique Visitor,即独立访客,对于实时计算中,也可以称为DAU(Daily Active User),即每日活跃用户,因为实时计算中的uv通常是指当日的访客数。
那么如何从用户行为日志中识别出当日的访客,有以下两点:
- 其一,是识别出该访客打开的第一个页面,表示这个访客开始进入应用。
- 其二,由于访客可以在一天中多次进入应用,所以要在一天的范围内进行去重。
2 从kafka中读取数据
工作流程如下:
(1)代码实现
public class UnionVistorApp {
public static void main(String[] args) throws Exception {
//TODO 1 基本环境准备
//1.1 流处理环境
StreamExecutionEnvironment env = StreamExecutionEnvironment.getExecutionEnvironment();
//1.2 设置并行度
env.setParallelism(4);
//TODO 2 检查点设置
// //2.1 开启检查点
// env.enableCheckpointing(5000L, CheckpointingMode.EXACTLY_ONCE);
// //2.2 设置检查点超时时间
// env.getCheckpointConfig().setCheckpointTimeout(60000L);
// //2.3 设置重启策略
// env.setRestartStrategy(RestartStrategies.fixedDelayRestart(3,3000L));
// //2.4 设置job取消后,检查点是否保留
// env.getCheckpointConfig().enableExternalizedCheckpoints(CheckpointConfig.ExternalizedCheckpointCleanup.RETAIN_ON_CANCELLATION);
// //2.5 设置状态后端 -- 基于内存 or 文件系统 or RocksDB
// env.setStateBackend(new FsStateBackend("hdfs://hadoop101:8020/ck/gmall"));
// //2.6 指定操作HDFS的用户
// System.setProperty("HADOOP_USER_NAME","hzy");
//TODO 3 从kafka中读取数据
//3.1 声明消费主题以及消费者组
String topic = "dwd_page_log";
String groupId = "union_visitor_app_group";
//3.2 获取kafka消费者对象
FlinkKafkaConsumer<String> kafkaSource = MyKafkaUtil.getKafkaSource(topic, groupId);
//3.3 读取数据封装流
DataStreamSource<String> kafkaDS = env.addSource(kafkaSource);
//TODO 4 对读取的数据进行类型转换 String -> JSONObject
SingleOutputStreamOperator<JSONObject> jsonObjDS = kafkaDS.map(JSON::parseObject);
jsonObjDS.print(">>>");
env.execute();
}
}
(2)测试
需要启动的进程:zookeeper、kafka、模拟生成日志jar包,logger.sh、UnionVistorApp、BaseLogApp。
- 启动logger.sh、zk、kafka
- 运行Idea中的BaseLogApp
- 运行Idea中的UniqueVisitApp
- 查看控制台输出
- 执行流程
模拟生成数据->日志处理服务器->写到kafka的ODS层(ods_base_log)->BaseLogApp分流->dwd_page_log->UniqueVisitApp读取输出
输出信息如下:
BaseLogApp
启动流::3> {
"common":{
"ar":"110000","uid":"45","os":"Android 11.0","ch":"360","is_new":"1","md":"Xiaomi Mix2 ","mid"