本文主要介绍如何使用Spark来对输入法用户使用日志数据进行分析,从数据源加载=》数据分析处理逻辑=》代码打包提交集群运行=》运行结果展示几个方面来进行介绍。
数据源
本文采用的数据是某输入法的用户使用日志数据,数据样本如下图所示:
这里的字段以“~”分割,分别为用户ID,产品ID,平台,版本,渠道,时间,等
数据分析案例代码
这里以上面数据作为数据源,在用户ID,产品ID,平台,版本与渠道5个维度的基础上以当天累积的方式来分析统计当天时段的产品使用用户数。分析思路如下:
- 首先加载全部当天全部源数据,然后进行数据过滤,取出我们需要的时间段数据:比如说我们需要统计2017年6月5日当天截止到19点这个时间点之前的产品用户数指标,我们需要做的就是将2017年6月5日0点-19点这个时间段的数据取出来,其他时间段的数据过滤出去;
- 数据维度提取与去重复处理:首先从上述数据中提取出我们需要的特征数据,比如说这里提取出(用户ID,产品ID,平台,版本,渠道)5个维度的数据,然后要把这个时间段中指定维度(产品ID,平台,版本,渠道)下相同用户记录删除,从而达到去重目的;
最后根据指定维度键来对用户数数据进行聚合累计,输出结果;
核心代码如下所示:
val atLogData = sc.textFile(mmPath + "/" + time)
val tempData = atLogData.map(_.split("~",-1))
.filter(f => {f(6).compare(TimeFunction.getNextTime(time,60)) <= 0})
//UserCount表分析:过滤数据、去重、分析统计用户数
val userCount = tempData.map(toUserAtDataCountObj).distinct()
.map(x => {((x._2,x._3,x._4,x._5),1)})
.reduceByKey(_+_)
.map{case((bizid, osid, version, channel),ucount)=>
Array(bizid, osid, version, channel, dbTime,ucount).mkString("~")}
userCount.coalesce(resultPartitionNum.toInt).saveAsTextFile(outPath+"/userCount/"+time)
sc.stop()
}
//UserCount源数据的转化处理函数
def toUserAtDataCountObj(d:Array[String])={
val Array(uid, bizid, osid, version, channel, ctm, firstUsed, functionName, ua, processName,
sunConsumingTime, maxConsumingTime, minConsumingTime, slowCount, count, ent, ext, exs) = d
(uid, bizid, osid, version, channel)
}
shell脚本提交到Spark集群
数据分析代码完成之后,将程序打包上传到集群中运行,这里主要介绍shell脚本提交运行方式
- 首先将编好的程序打包,本项目采用maven构建,故这里使用maven命令进行打包:mvn clean package; 得到项目jar包;
- 编写shell脚本,配置集群提交相关设置;
将项目jar包和shell脚本上传至自己的Linux工作目录下,然后利用bash -x XXX.sh param1 param2 param3….命令进行提交,集群运行输出结果文件
如本次程序提交脚本配置包含两个文件,一个是基本configs.sh,一个是针对本程序的提交脚本userCount.sh,代码示例如下:
#!/bin/bash
source ~/.bashrc
WORKPATH=$(cd "$(dirname "$0")/"; pwd);
# ------------------ import extern files ------------------
source $WORKPATH/configs.sh ${DATE};
#################################################################
SPARKCALSS=com.iflytek.app.batch.performanceV2.ActivityPerformanceByHour
DATE=$1
TIME=$2
resultPartitionNum=4
#################################################################
cd $WORKPATH;
hadoop fs -rm -r ${mmLogStatPath}/*/${TIME} || true;
for (( i = 0; i < 1; i++ )); do
$SPARK_HOME/bin/spark-submit \
--master $SPARKMASTER \
--class $SPARKCALSS \
--executor-cores 6 \
--num-executors 10 \
--driver-memory 3g \
--executor-memory 6g \
--queue ${QUEUE} \
$GROOTSPARKJAR \
${mmLogOutPath} \ // 输入数据路径
${mmLogStatPath} \ //输出数据路径
${resultPartitionNum} \ //结果文件分片数量
${TIME} \ //统计时间点
cluster //集群部署模式
done
configs.sh文件中主要配置自己的hdfs输入数据源位置与输出结果文件位置,这里不做展示。
结果展示
集群运行结果如下图:
输出结果如下图所示:
部分文件结果展示
至此,完成了一个完整的Spark数据分析,分析结果可以进一步利用python脚本导入到目标数据库,为上层应用提供数据支持。