一、Spark项目开发流程回顾
二、Spark应用程序开发
添加hadoop-client版本、添加cdh仓库、打包注意事项、上传服务器使用rz命令、spark-submit提交打的jar包进行运行、结果控制台输出&hdfs输出、多个文件输入、输入文件通配符匹配、输出结果排序
开发WordCountApp使我们了解到了一个完整的项目开发流程;测试可以直接在spark-shell中进行测试。
需求:求用户访问量的TOP5:
需求分析:
1)、把end_user_id拿出来
2)、拿到用户对应的访问量,使用map赋上一个1,使用reduceByKey统计
3)、Top5
需求拿到以后详细设计就是一个填空题目:
1、打开Hive客户端,创建一张page_views表:
create table page_views(track_time string,url string,session_id string,referer string,ip string,end_user_id string,city_id string)row format delimited fields terminated by '\t';
2、把本地准备好的数据加载进去:
load data local inpath '/home/hadoop/data/page_views.dat' overwrite into table page_views;
3、编写SQL,求的用户访问量的Top5:
select end_user_id,count(*) as cend_user_id c
NULL 60871
123626648 40
116191447 38
122764680 34
85252419 30 from page_views group by end_user_id order by c desc limit 5;
4、输出结果:
2、Spark-Core实现TopN:
hive (default)> select * from page_views limit 1;
OK
page_views.track_time page_views.url page_views.session_id page_views.referer page_views.ip page_views.end_user_id page_views.city_id
2013-05-19 13:00:00 http://www.taobao.com/17/?tracker_u=1624169&type=1 B58W48U4WKZCJ5D1T3Z9ZY88RU7QA7B1 http://hao.360.cn/ 1.196.34.243 NULL-1
1、读入文件:
val textFile = sc.textFile("file:///home/hadoop/data/page_views.dat")
2、使用split为它进行分割顺带取出第五位,并使用map为它赋上1个1;使用take(5)取值验证:
val user_id = textFile.map(x =>(x.split("\t")(5),1))
scala> user_id.take(5)
res7: Array[(String, Int)] = Array((NULL,1), (134939954,1), (NULL,1), (NULL,1), (NULL,1))
3、使用reduceByKey为所有相同的key进行相加,把x/y顺序颠倒使用sortByKey进行排序,排序完成后顺序再搞回来,take(5)取出前5条数据:
scala> user_id.reduceByKey(_+_).map(x =>(x._2,x._1)).sortByKey(false).map(x =>(x._2,x._1)).take(5).foreach(println)
(NULL,60871)
(123626648,40)
(116191447,38)
(122764680,34)
(85252419,30)
1、IDEA的代码如下:
package com.ruozedata.bigdata.SparkCore01
import org.apache.spark.{SparkConf, SparkContext}
object TopApp {
def main(args: Array[String]): Unit = {
val sparkConf = new SparkConf()
val sc=new SparkContext(sparkConf)
val page_views = sc.textFile(args(0))
// val page_views = sc.textFile("file:///home/hadoop/data/page_views.dat")
//获取到user_id,tab键是分割符,取出第5位,使用map进行赋值1
val user_id = page_views.map(x =>(x.split("\t")(5),1))
user_id.reduceByKey(_+_).map(x =>(x._2,x._1)).sortByKey(false).map(x =>(x._2,x._1)).take(5).foreach(println)
sc.stop()
}
}
2、同样的打jar包,上传到服务器中去,使用spark-submit进行提交,如上代码是直接在控制台上打印出来的
3、此处如何修改使得其打印到hdfs上的目录中去?
引申:在工作中,很多场景的统计,你都可以看到WordCount的影子。
拿到需求以后:
1)、分析
2)、功能拆解:中文描述 《-- 详细设计说明书
3)、代码的开发:代码的实现 《–码农干的事情
1、key-value这样的数据格式:
1 24
2 34
2、代码如下
package com.ruozedata.bigdata.SparkCore01
import org.apache.spark.{SparkConf, SparkContext}
object AvgApp {
def main(args: Array[String]): Unit = {
val sparkConf = new SparkConf()
val sc = new SparkContext(sparkConf)
//读取文件
val textFile = sc.textFile("file:///home/hadoop/data/sample_age_data")
//split取出年龄数据:
val ageData = textFile.map(x =>x.split(" ")(1))
//求出年龄总和:
val totalData = ageData.map(x =>x.toInt).reduce(_+_)
//计算出总人数:
val countPeople = textFile.count()
//计算出平均年龄 --> 总年龄/总人数
val avgData = totalData/countPeople
sc.stop()
}
}
IDEA中的每一步都可以在相应的spark-shell中进行测试,但是公式中不能定义和算子同名的变量,否则运行的时候系统会识别不了。
数据源:id、性别、身高
id | 性别 | 身高 |
---|---|---|
1 | F | 185 |
分析:
1)、取出性别:一个分组groupBy
RDD ⇒ MRDD + FRDD(一个RDD拆分男RDD + 女RDD)
2)、max min由于结构的特殊性,直接使用max、min就行
1、读取数据:
val lines = sc.textFile("file:///home/hadoop/data/people.txt")
2、拿到MRDD,得到最高身高和最低身高:
scala> val FRDD = data.map(x => x.split(" ")).map(line => {val gender = line(1); val height = line(2); (gender,height)}).filter(x => (x._1) =="M")
FRDD: org.apache.spark.rdd.RDD[(String, String)] = MapPartitionsRDD[46] at filter at <console>:25
3、获取最高、最低身高
FRDD.map(x =>(x._2)).max
FRDD.map(x =>(x._2)).min
在spark-shell中这样开发测试是没有问题的,解析:先spilt(" ")使用空格进行分割,取出性别和身高共两列,filter过滤出性别中是M的数据;
import org.apache.spark.{SparkConf, SparkContext}
object InfoApp {
def main(args: Array[String]): Unit = {
val sparkConf = new SparkConf().setMaster("local[2]").setAppName("Info")
val sc = new SparkContext(sparkConf)
// val data = sc.textFile("hdfs://hadoop004:9000/data/input/people.txt")
val data=sc.textFile("C:/Users/Administrator/Downloads/people.txt")
val MRDD = data.map(x =>x.split(" ")).map(line =>
{
val gender = line(1)
val height = line(2)
(gender,height)}
).filter(x =>(x._1)=="M")
println("男生中身高最高的:" + MRDD.map(x =>(x._2)).max)
sc.stop()
}
}
//我在IDEA启动的时候出现了报错