|NO.Z.00029|——————————|^^ 重要 ^^|——|Hadoop&PB级数仓.V13|——|PB数仓.v13|会员活跃度分析|Hive on MR&活跃&新增&留存会员|数据加载|内存分配调整map&reduce数量|

一、高仿日启动数据测试:
### --- 高防日启动数据测试

~~~     数据采集 => 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) => 14map => 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文件来限制

~~~     此方案是全局的参数,不建议使用。
~~~     若是使用此方案,会对其它人的作业参数影响。
~~~     建议使用脚本文件来调整,只影响当前作业。

 
 
 
 
 
 
 
 
 

Walter Savage Landor:strove with none,for none was worth my strife.Nature I loved and, next to Nature, Art:I warm'd both hands before the fire of life.It sinks, and I am ready to depart
                                                                                                                                                   ——W.S.Landor

 

 

posted on   yanqi_vip  阅读(33)  评论(0编辑  收藏  举报

相关博文:
阅读排行:
· 无需6万激活码!GitHub神秘组织3小时极速复刻Manus,手把手教你使用OpenManus搭建本
· Manus爆火,是硬核还是营销?
· 终于写完轮子一部分:tcp代理 了,记录一下
· 别再用vector<bool>了!Google高级工程师:这可能是STL最大的设计失误
· 单元测试从入门到精通
< 2025年3月 >
23 24 25 26 27 28 1
2 3 4 5 6 7 8
9 10 11 12 13 14 15
16 17 18 19 20 21 22
23 24 25 26 27 28 29
30 31 1 2 3 4 5

导航

统计

点击右上角即可分享
微信分享提示