一、高仿日启动数据测试:
### --- 高防日启动数据测试
~~~ 数据采集 => ODS => DWD => DWS => ADS> MySQL
~~~ 活跃会员、新增会员、会员留存
~~~ DAU: Daily Active User(日活跃用户)
~~~ MAU: monthly active user(月活跃用户)
~~~ 假设App的DAU在1000W左右,日启动数据大概 1000W 条;
~~~ 测试3天的数据:7月21日、7月22日、7月23日。1000W条数据约3.5G+,每条记录约370字节。
### --- 实验概述
~~~ 选择 7月21日 的启动日志进行测试
~~~ 使用 flume 采集数据(采集3天的数据)
~~~ 修改flume的参数:1G滚动一次;加大channel缓存;加大刷新 hdfs 的缓存
二、Flume采集数据:hive通过Flume采集数据到hdfs下
### --- 创建flume配置conf文件:建议配置参数
~~~ # 建议配置:
~~~ # 自己环境可根据实际情况调节
# 配置文件滚动方式(文件大小1G)
a1.sinks.k1.hdfs.rollSize = 1073741824
a1.channels.c1.capacity = 500000
a1.channels.c1.transactionCapacity = 20000
# 向hdfs上刷新的event个数
a1.sinks.k1.hdfs.batchSize = 10000
### --- 创建Flume配置文件
[root@hadoop02 ~]# vim /data/yanqidw/conf/flume-log2hdfs4.conf
a1.sources = r1
a1.sinks = k1
a1.channels = c1
# taildir source
a1.sources.r1.type = TAILDIR
a1.sources.r1.positionFile = /data/yanqidw/conf/startlog_position.json
a1.sources.r1.filegroups = f1 f2
a1.sources.r1.filegroups.f1 = /data/yanqidw/logs/start/.*log
a1.sources.r1.headers.f1.logtype = start
a1.sources.r1.filegroups.f2 = /data/yanqidw/logs/event/.*log
a1.sources.r1.headers.f2.logtype = event
# 自定义拦截器
a1.sources.r1.interceptors = i1
a1.sources.r1.interceptors.i1.type = cn.yanqi.dw.flume.interceptor.LogTypeInterceptor$Builder
# memorychannel
a1.channels.c1.type = memory
a1.channels.c1.capacity = 100000
a1.channels.c1.transactionCapacity = 2000
# hdfs sink
a1.sinks.k1.type = hdfs
a1.sinks.k1.hdfs.path = /user/data/logs/%{logtype}/dt=%{logtime}/
a1.sinks.k1.hdfs.filePrefix = startlog
a1.sinks.k1.hdfs.fileType = DataStream
# 配置文件滚动方式(文件大小10M)(环境资源有限,生产环境根据实际情况来定,不然会造成很多小文件)
a1.sinks.k1.hdfs.rollSize = 10240000
a1.sinks.k1.hdfs.rollCount = 0
a1.sinks.k1.hdfs.rollInterval = 0
a1.sinks.k1.hdfs.idleTimeout = 0
a1.sinks.k1.hdfs.minBlockReplicas = 1
# 向hdfs上刷新的event的个数
a1.sinks.k1.hdfs.batchSize = 10000
# Bind the source and sink to the channel
a1.sources.r1.channels = c1
a1.sinks.k1.channel = c1
三、Flume采集数据:hive通过Flume采集数据到hdfs下
### --- 清理工作:
~~~ 清理本地环境
~~~ 删除本地元数据文件、日志、hdfs等文件
rm -rf /data/yanqidw/conf/startlog_position.json
rm -rf /data/yanqidw/logs/start/*
rm -rf /data/yanqidw/logs/event/*
~~~ # 清理hdfs数据
hdfs dfs -rm -r -f /user/data/logs/start/dt=2020-07-21
hdfs dfs -rm -r -f /user/data/logs/start/dt=2020-07-22
hdfs dfs -rm -r -f /user/data/logs/start/dt=2020-07-23
### --- 启动flume
~~~ # 启动historyserver
/opt/yanqi/servers/hadoop-2.9.2/sbin/mr-jobhistory-daemon.sh start historyserver
~~~ # 启动flume
flume-ng agent --conf /opt/yanqi/servers/flume-1.9.0/conf \
--conf-file /data/yanqidw/conf/flume-log2hdfs4.conf \
-name a1 -Dflume.root.logger=INFO,console
### --- 写入日志数据
~~~ # 写日志:
~~~ 该代码是更改日志时间为特定时间
cd /data/yanqidw/jars/
java -cp data-generator-1.1-SNAPSHOT-jar-with-dependencies.jar \
com.yanqi.ecommerce.AppStart 1 10000000 2020-07-21 \
>/data/yanqidw/logs/start/start0721.log
java -cp data-generator-1.1-SNAPSHOT-jar-with-dependencies.jar \
com.yanqi.ecommerce.AppStart 6000000 16000000 2020-07-22 \
>/data/yanqidw/logs/start/start0722.log
java -cp data-generator-1.1-SNAPSHOT-jar-with-dependencies.jar \
com.yanqi.ecommerce.AppStart 8000000 18000000 2020-07-23 \
>/data/yanqidw/logs/start/start0723.log
### --- 检查hdfs文件是否到达
~~~ 检查 hdfs 文件是否到达
~~~ 1个文件大小3.5G,时间4分钟左右
[root@hadoop02 ~]# hdfs dfs -ls /user/data/logs/start/dt=2020-07-21
Found 4 items
-rw-r--r-- 5 root supergroup 10268344 2021-10-02 21:58 /user/data/logs/start/dt=2020-07-21/startlog..1633183121972
-rw-r--r-- 5 root supergroup 10268071 2021-10-02 21:58 /user/data/logs/start/dt=2020-07-21/startlog..1633183121973
-rw-r--r-- 5 root supergroup 10268135 2021-10-02 21:58 /user/data/logs/start/dt=2020-07-21/startlog..1633183121974
-rw-r--r-- 5 root supergroup 5885342 2021-10-02 22:22 /user/data/logs/start/dt=2020-07-21/startlog..1633183121975
四、Hive on MR
### --- 语法:向ODS层下加载数据:
~~~ 执行脚本语法
~~~ 定义脚本地址变量
SCRIPT_HOME=/data/yanqidw/script/member_active
~~~ # ODS层与HDFS下数据文件建立关联
~~~ # 加载 ODS 层数据(文件与表建立关联)
sh $SCRIPT_HOME/ods_load_startlog.sh 2020-07-21
### --- 语法:在DWD层下解析json数据
~~~ # 加载 ODS 层数据(解析json数据)
~~~ number of mappers: 14; number of reducers: 0
~~~ 是一个 map-only 的 Task;只对输入的数据做格式上的转换,没有聚合操作(即没有reduce task)
~~~ mapred.max.split.size=256M;3.5G / 256M = 14 Mapper Task
sh $SCRIPT_HOME/dwd_load_startlog.sh 2020-07-21
### --- 语法:计算活跃会员
~~~ # 活跃会员
~~~ number of mappers: 3; number of reducers: 2
~~~ 调整了task的内存分配(根据实际情况分配)
~~~ 任务执行时间:3.5 + 3 + 3 = 10分钟
~~~ ODS(Text) => 14个map => DWD(parquet) => 小文件合并 256M切分 =>3 map
sh $SCRIPT_HOME/dws_load_member_start.sh 2020-07-21
sh $SCRIPT_HOME/ads_load_member_active.sh 2020-07-21
### --- 语法:计算新增会员
~~~ # 新增会员
sh $SCRIPT_HOME/dws_load_member_add_day.sh 2020-07-21
sh $SCRIPT_HOME/ads_load_member_add.sh 2020-07-21
### --- 语法:计算留存会员
~~~ # 会员留存
sh $SCRIPT_HOME/dws_load_member_retention_day.sh 2020-07-21
sh $SCRIPT_HOME/ads_load_member_retention.sh 2020-07-21
### --- 语法:查询相关表,数据是否映射成功。
select count(*) from ods.ods_start_log where dt='2020-07-21';
select count(*) from dwd.dwd_start_log where dt='2020-07-21';
select count(*) from dws.dws_member_start_day where dt='2020-07-21';
select count(*) from dws.dws_member_start_week where dt='2020-07-21';
select count(*) from dws.dws_member_start_month where dt='2020-07-21';
select count(*) from dws.dws_member_add_day where dt='2020-07-21';
select count(*) from dws.dws_member_retention_day where dt='2020-07-21';
select count(*) from ads.ads_member_active_count where dt='2020-07-21';
select count(*) from ads.ads_new_member_cnt where dt='2020-07-21';
select count(*) from ads.ads_member_retention_count where dt='2020-07-21';
select count(*) from ads.ads_member_retention_rate where dt='2020-07-21';
一、操作实例:向ODS层下加载数据
### --- 定义脚本地址变量
[root@hadoop02 ~]# SCRIPT_HOME=/data/yanqidw/script/member_active
### --- ODS层与HDFS下数据文件建立关联
~~~ # 加载 ODS 层数据(文件与表建立关联)
[root@hadoop02 ~]# sh $SCRIPT_HOME/ods_load_startlog.sh 2020-07-21
~~~ # 查看数据是否加载进来
hive (default)> show partitions ods.ods_start_log;
OK
partition
dt=2020-07-21
hive (default)> select count(*) from ods.ods_start_log where dt='2020-07-21' limit 10;
9999
二、操作实例:把数据从ODS层加载到DWD层中
### --- 把数据从ODS层加载到DWD层中
~~~ # 加载 ODS 层数据到DWD中(解析json数据)
~~~ number of mappers: 14; number of reducers: 0
~~~ 是一个 map-only 的 Task;只对输入的数据做格式上的转换,没有聚合操作(即没有reduce task)
~~~ mapred.max.split.size=256M;3.5G / 256M = 14 Mapper Task
[root@hadoop02 ~]# sh $SCRIPT_HOME/dwd_load_startlog.sh 2020-07-21
hive (dwd)> set mapred.max.split.size;
mapred.max.split.size=256000000 # 取决于这个参数
### --- 查看数据是否加载dwd层
~~~ # 查看解析的数据
hive (default)> show partitions dwd.dwd_start_log;
partition
dt=2020-07-21
hive (default)> select count(*) from dwd.dwd_start_log where dt='2020-07-21';
9999 # 解析到的数据个数
三、操作实例:计算活跃会员
### --- 把活跃会员加载到dws层
~~~ # 活跃会员
~~~ number of mappers: 3; number of reducers: 2
~~~ 调整了task的内存分配(根据实际情况分配)
~~~ 任务执行时间:3.5 + 3 + 3 = 10分钟
~~~ ODS(Text) => 14个map => DWD(parquet) => 小文件合并 256M切分 =>3 map
[root@hadoop02 ~]# sh $SCRIPT_HOME/dws_load_member_start.sh 2020-07-21
### --- 查看活跃会员是否加载到DWS层
hive (default)> show partitions dws.dws_member_start_day;
partition
dt=2020-07-21
hive (default)> select count(*) from dws.dws_member_start_day where dt='2020-07-21';
9999
hive (default)> show partitions dws.dws_member_start_week;
partition
dt=2020-07-21
hive (default)> select count(*) from dws.dws_member_start_week where dt='2020-07-21';
9999
hive (default)> show partitions dws.dws_member_start_month;
partition
dt=2020-07-21
hive (default)> select count(*) from dws.dws_member_start_month where dt='2020-07-21';
9999
### --- 计算活跃会员
[root@hadoop02 ~]# sh $SCRIPT_HOME/ads_load_member_active.sh 2020-07-21
~~~ # 查看计算结果
~~~ 对于第一天的数据来说,日活跃,周活跃,月活跃数据是一样的
hive (default)> show partitions ads.ads_member_active_count;
partition
dt=2020-07-21
hive (default)> select * from ads.ads_member_active_count where dt='2020-07-21';
ads_member_active_count.day_count ads_member_active_count.week_count ads_member_active_count.month_count ads_member_active_count.dt
9999 9999 9999 2020-07-21
四、操作实例:计算新增会员
### --- 把新增会员加载到dws层
~~~ # 加载新增会员到dws层
[root@hadoop02 ~]# sh $SCRIPT_HOME/dws_load_member_add_day.sh 2020-07-21
~~~ # 查看新增会员是否加载到dws层
hive (default)> select count(*) from dws.dws_member_add_day where dt='2020-07-21';
9999
### --- 计算新增会员
[root@hadoop02 ~]# sh $SCRIPT_HOME/ads_load_member_add.sh 2020-07-21
~~~ # 对于第一天的数据来说,日新增会员是一样的
hive (default)> show partitions ads.ads_new_member_cnt;
partition
dt=2020-07-21
hive (default)> select * from ads.ads_new_member_cnt where dt='2020-07-21';
ads_new_member_cnt.cnt ads_new_member_cnt.dt
9999 2020-07-21
五、操作实例:计算留存会员
### --- 把留存会员加载到dws层
[root@hadoop02 ~]# sh $SCRIPT_HOME/dws_load_member_retention_day.sh 2020-07-21
~~~ # 查看留存会员是否加载到dws层
hive (default)> show partitions dws.dws_member_retention_day;
OK
partition
dt=2020-07-21
hive (default)> select count(*) from dws.dws_member_retention_day where dt='2020-07-21';
0 # 因为它是第一天,是没有留存率的,所以说是没有数据的
### --- 计算留存会员
~~~ 是没有数据的,因为是第一天,所以说是没有数据的。
~~~ 在执行其它的日期的时候会计算出来。
[root@hadoop02 ~]# sh $SCRIPT_HOME/ads_load_member_retention.sh 2020-07-21
hive (default)> show partitions ads.ads_member_retention_count;
partition
dt=2020-07-21
hive (default)> select * from ads.ads_member_retention_count where dt='2020-07-21';
OK
附录一:报错处理一
### --- 报错现象:
~~~ 卡在这个位置不会动,数据没有加载
~~~ 在执行这个的时候,把history打开,用于监控错误信息
[root@hadoop02 ~]# sh $SCRIPT_HOME/dwd_load_startlog.sh 2020-07-21
Cannot run job locally: Input Size (= 368902544) is larger than hive.exec.mode.local.auto.inputbytes.max (= 134217728)
2021-10-02 20:14:22,095 Stage-1 map = 0%, reduce = 0%
附录二:报错处理二
### --- 报错现象
Error during job, obtaining debugging information...
FAILED: Execution Error, return code 2 from org.apache.hadoop.hive.ql.exec.mr.MapRedTask
MapReduce Jobs Launched:
Stage-Stage-1: HDFS Read: 0 HDFS Write: 0 FAIL
Total MapReduce CPU Time Spent: 0 msec
~~~ # 通过historyserver查看报错现象
Error:Java heap space # 内存比较小
### --- 报错分析:
~~~ 内存分配问题
### --- 解决方案:
~~~ 解决方案一:加大内存:合理的分配内存
~~~ 解决方案二:调整map和reduce数量
### --- 解决方案一:
~~~ # 调整map和reduce数量方案一:通过修改yarn计算资源来限制
~~~ 给map、reduce task分配合理的内存;
~~~ map、reduce task处理合理的数据现在情况下map task分配了多少内存?
~~~ 使用的是缺省参数每个task分配200M内存【mapred.child.java.opts】
~~~ 每个节点:8 core / 32G;mapred.child.java.opts = 3G
~~~ # 设置yarn集群的map和reduce分配合理内存的参数
[root@hadoop01 ~]# vim /opt/yanqi/servers/hadoop-2.9.2/etc/hadoop/yarn-site.xml
<!-- 设置map、reduce合理内存参数 -->
<property>
<name>mapred.child.java.opts</name>
<value>-Xmx3072m</value>
</property>
~~~ # 发送到其它节点
[root@hadoop01 ~]# rsync-script /opt/yanqi/servers/hadoop-2.9.2/etc/hadoop/yarn-site.xml
~~~ # 重启yarn服务
[root@hadoop01 ~]# stop-yarn.sh
[root@hadoop01 ~]# start-yarn.sh
~~~ # 通过jps查看查看进程:YarnClid可以看到内存配置情况
[root@hadoop01 ~]# jps
17245 YarnClid
[root@hadoop01 ~]# ps -ef | grep 17245
~~~ 输出配置参数
~~~ -Xmx3072m ~~~
### --- 解决方案二:
~~~ # 调整map和reduce数量方案二:通过脚本文件来限制
# 在hive下调整map个数:
mapred.max.split.size=256000000
# 调整reduce个数:
hive.exec.reducers.bytes.per.reducer
hive.exec.reducers.max
~~~ # 配置参数:调整hive下map和reduce个数及大小
[root@hadoop02 ~]# vim /data/yanqidw/script/member_active/dws_load_member_start.sh
hive \
-hiveconf mapred.max.split.size=128000000 \
-hiveconf hive.exec.reducers.bytes.per.reducer=128000000 \
-e "$sql"
### --- 解决方案三:
~~~ # 调整map和reduce数量方案三:通过修改hive-site.xml文件来限制
~~~ 此方案是全局的参数,不建议使用。
~~~ 若是使用此方案,会对其它人的作业参数影响。
~~~ 建议使用脚本文件来调整,只影响当前作业。