Spark大数据比赛经验记录(含sparksubmit 提交方法)

来源:互联网 发布:高鹗续写红楼梦知乎 编辑:程序博客网 时间:2024/05/21 08:43

十月底, 参加了公司的一个spark大数据比赛, 题目比较简单, 但是由于自己缺乏此方面的业务知识, 所以对我来说解答的过程还是很有收获的 , 现在记录如下:

题目

数据表:
CREATE EXTERNAL TABLE fact_ipp_flux_limit(
clttime timestamp,
clttimeint bigint,
imsi string,
ci bigint,
url string,
tcpwrldelay bigint
)
PARTITIONED BY (
reportdate string,
reporthour int,
reportneid int)
ROW FORMAT DELIMITED FIELDS TERMINATED BY ‘,’
STORED AS TEXTFILE LOCATION ‘/zxvmax/telecom/cn/test_data/fact_ipp_flux_limit’;

该数据表是统计的某地区电信用户手机上网情况, 其中clttime是访问对应url的时间, imsi是手机卡标识, ci是小区ID, url则是访问链接. 数据如下图所示:

数据示例

问题 :
1. 根据提供的数据,输出每五分钟,人流量最大的TOP3小区。(简单)
时间:14:00 – 17:00
字段:时间(clttime),小区(ci), 用户(imsi)
2. 根据URL识别搜索引擎的关键词,并给出搜索热度排名。(中等)
时间:00:00 – 23:59
字段:url,时间(clttime)
3. 根据URL识别什么时段大家更喜欢看新闻。(中等)
时间:00:00 – 23:59
字段:url,时间(clttime)
4. 根据URL识别最受欢迎的网站。(中等)
时间:00:00 – 23:59
字段:url,时间(clttime)**

提交指南

我们以wordcount为例介绍下在linux环境下的提交方式

示例代码(wordcount.scala):

package bigdataimport org.apache.spark.SparkConfimport org.apache.spark.SparkContextimport org.apache.spark.SparkContext._object WordCount{    def main(args: Array[String])    {        if (args.length < 1)        {            System.err.println("Usage: <file>")            System.exit(1)        }        val conf = new SparkConf()        val sc = new SparkContext(conf)        val line = sc.textFile(args(0))        val array = line.flatMap(_.split(" ")).map((_, 1)).reduceByKey(_ + _)        array.saveAsTextFile("/odpp/files/output")        sc.stop()    }}

编译

scalac -classpath /home/mr/spark/lib/spark-assembly-1.4.1-hadoop2.5.0-cdh5.3.2.jar -d wordcount.jar wordcount.scala
此处要注意scala的版本要与spark-assembly的scala编译版本最好一致, 不然可能在运行时出错.上述jar是由scala 2.10.4编译的

提交

spark-submit  --master yarn-cluster --queue user07_space --driver-memory 3G --executor-memory 2G --num-executors 3 --class bigdata.wordcount /home/wordcount.jar  xxx.txt  其中,(./spark-submit --help可以查看详情)  yarn-cluster意思是放到yarn集群中执行作业, 如果单机模式的话可以用--master local[8]  --queue gzwspace 指定作业执行的用户空间,  --driver-memory 3G 指定启动作业时需要的内存大小  --executor-memory 2G 指定执行作业时,每个集群节点的内存大小  --num-executors 3 执行执行的节点数  --class bigdata.wordcount 指定class名  /home/wordcount.jar 指定jar包  xxx.txt  指定args参数

–master参数的补充说明:

Master URL Meaning local 本地单线程 local[K] 本地K个线程, 建议设置城与cpu核数想相同 local[*] 本地多线程运行, 运行时的线程与cpu核数相同 spark://HOST:PORT 链接Spark Standlone集群管理器主机,默认端口为7077 yarn-client 采用client模式链接Yarn资源管理器, 集群位置信息配置在HADOOP_CONF_DIR或 YARN_CONF_DIR变量中 yarn-cluster 采用CLuster模式链接Yarn资源管理器, 集群位置信息与上相同 simr://HOST:PORT 兼容Hadoop 1.0 mesos://HOST:PORT 链接Mesos资源管理器

用到的点

  1. 使用spark-shell时候, 可以直接使用sqlContext提交sql语句, 比如:
    sqlContext.sql(“select * from fact_ipp_flux_limit limit 10”).show
    show是查看, 或者也可以打印: .collect.foreach(println)
  2. 但是使用spark-submit提交jar作业的时候, 要自己定义sqlContext:
    val conf = new SparkConf()
    val sc = new SparkContext(conf)
    val sqlContext = new HiveContext(sc)

  3. shuffle时候task数目优化(经验值是可用cpu核数的三倍)

    val buckets = try {  sc.getConf.get("spark.cores.max").toInt * 3} catch {  case e: Exception => 200}sqlContext.sql(s"set spark.sql.shuffle.partitions=$buckets")

    粗略的解释就是:如果这个值太低, 也就是task任务数太少, 使得每隔task处理时间过长容易Straggle, 而且有GC. 如果太大就有很多任务启动开销. 虽然设置大一点可以解决GC, 但有时候大了也没用是因为有数据倾斜(某一个task处理了大量任务,而其他task是清闲的)

  4. url解码, 使用java的URLDecoder

    try {        result = java.net.URLDecoder.decode("%e4%bd%a0%e5%a5%bd", ENCODE);//encode可有可无,代表编码    } catch (UnsupportedEncodingException e) {        e.printStackTrace();    }
  5. 零宽断言来提取搜索引擎词汇,如 百度的链接:

    """(?<=&word=).*(?=(&|$))""".r findFirstIn """fdsfsd&word=fdsfsdfsfdsf"""
  6. 第一题里, 每五分钟, 可以将时间换算成分钟然后 /5, 数值相同的即是在同一个五分钟内

  7. 用开窗函数取每个分组的top3值: row_number() over (partition by hour,minute5 order by usercount desc)
  8. spark里的dataframe相关api要多学一下比如show, select等都很有用.

结论(简单版)

  1. 题目一
    这里写图片描述
  2. 题目二
    这里写图片描述
  3. 题目三
    这里写图片描述
  4. 题目四
    这里写图片描述

源代码

// 此次比赛提供的spark-assembly-1.4.1-hadoop2.5.0-cdh5.3.2版本是由scala2.10.4编译的// 但是环境上scala版本为2.11.8, 执行会报错, 所以编译时请选择2.10.4的环境package bigdataimport org.apache.spark.sql.SQLContextimport org.apache.spark.sql.hive.HiveContextimport org.apache.spark.{SparkConf, SparkContext}import scala.util.Tryobject SparkGame {  def main(args: Array[String]) {    if (args.length < 1) {      System.err.println("============请在提交时添加参数: 1,2,3,4分别代表四个题目================")      System.exit(1)    }    val conf = new SparkConf()    val sc = new SparkContext(conf)    val sqlContext = new HiveContext(sc)    val buckets = try {      sc.getConf.get("spark.cores.max").toInt * 3    } catch {      case e: Exception => 200    }    sqlContext.sql(s"set spark.sql.shuffle.partitions=$buckets")    try {      args(0) match {        case "1" => top3Cell(sqlContext)        case "2" => searchHot(sqlContext)        case "3" => hotNews(sqlContext)        case "4" => popularWebSite(sqlContext)        case _ =>             System.err.println("=========参数错啦=========")            System.exit(1)      }    } catch {      case e: Exception => e.printStackTrace()    } finally {      sc.stop()    }  }  // 第一题 各时段Top3小区  private def top3Cell(sqlContext: HiveContext): Unit = {    def sql =      """         select ci,usercount,date,hour,minute5*5 as minute         from (          select ci,date,hour,minute5,usercount,row_number() over (partition by hour,minute5 order by usercount desc) as rn          from(            select date,count(distinct imsi) as usercount,ci,hour,minute5            from (              select reportdate as date,reporthour as hour,cast(minute(clttime)/5 as int) as minute5,ci,imsi              from fact_ipp_flux_limit              where reportdate='2016-05-28' and reporthour in (14,15,16) and length(ci)=15            ) a            group by hour,minute5,ci,date          ) b         ) c where rn<=3      """    val temp = sqlContext.sql(sql).rdd.persist    temp.collect.foreach(println)  }  // 第二题 搜索引擎关键词排名  private def searchHot(sqlContext: HiveContext): Unit = {    def sql =      """  select url from fact_ipp_flux_limit      """    val baiduReg = """(?<=&word=).*(?=(&|$))""".r    val shenmaReg = """(?<=s\?q=).*(?=(&|$))""".r    val sogouReg = """(?<=keyword=).*(?=&)""".r    val q360Reg = """(?<=index.php\?q=).*(?=&)""".r    val searchKW = sqlContext.sql(sql).rdd.map(row => row.getString(0)).filter(_.length > 1)      .map { url =>        val baidu = baiduReg findFirstIn url        val shenma = shenmaReg findFirstIn url        val sogou = sogouReg findFirstIn url        val q360 = q360Reg findFirstIn url        val list = List(baidu, shenma, sogou, q360).filter(_ != None)        if (list.isEmpty)          ""        else          Try {            list.head.getOrElse("").split("&").head          }.getOrElse("")      }.filter(_.length > 0)      .map { x => Try(java.net.URLDecoder.decode(x, "utf-8")).getOrElse("") }      .filter(_.length > 0)      .map((_, 1)).reduceByKey(_ + _)      .sortBy(_._2, ascending = false).persist    searchKW.take(150).foreach(println)  }  // 第三题 新闻热度   private def hotNews(sqlContext: HiveContext): Unit = {   import sqlContext.implicits._    def sql =      """  select imsi,url,reporthour from fact_ipp_flux_limit       """      val newsWebs = List("info.3g.qq.com", "kb.qq.com", "sina.cn", "toutiao.com", "yidianzixun", "ifeng.com", "sohu.com", "3g.163.com", "xinhuanet", "people.com", "myzaker", "weibo.com","news")       val hotNews = sqlContext.sql(sql).rdd.map(row => (row.getString(0), row.getString(1), row.getInt(2))).filter(_._2.length > 1)        .map { urlInfo => if (newsWebs.exists(urlInfo._2.contains(_))) URLInfo(urlInfo._1, "1", urlInfo._3) else URLInfo(urlInfo._1, "0", urlInfo._3) }      hotNews.toDF.registerTempTable("newsurl")      def sql2 =        """select sum(p) as hotrate,reporthour                   from (                     select count(case when url=1 then 1 else null end)/count(*) as p,imsi,reporthour                     from newsurl                     group by imsi,reporthour                   ) as userrate                   group by reporthour"""    sqlContext.sql(sql2).show()}  // 第四题  private def popularWebSite(sqlContext: HiveContext): Unit = {    def sql =      """    select url from fact_ipp_flux_limit          """    val popularRDD = sqlContext.sql(sql).rdd      .map(row => row.getString(0))      .filter(_.length > 1)      .map(x => filterDomin(x))      .filter(_.length > 1)      .map(x => x.split("\\.").init.last + "." + x.split("\\.").last)      .map((_, 1)).reduceByKey(_ + _)      .sortBy(_._2, ascending = false).persist    //popularRDD.saveAsTextFile("/odpp/spaces/user07_space/files/popularwebsite")    popularRDD.take(150).foreach(println)  }  private def filterDomin(str: String): String = {    str.split("/", -1).dropRight(1).find(x => findTopDomain(x)).getOrElse("")  }  private def findTopDomain(x: String): Boolean = {    val domain = List(".cn", ".com", ".net", ".org", ".gov", ".edu")    domain.exists(x.contains(_))  }}case class URLInfo(imsi: String, url: String, reporthour: Int)
1 0
原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 高速过路费没交怎么办 24岁血压高怎么办 高压147低压110怎么办 宣武医院怎么办住院证 自主择业后悔了怎么办 建行app闪退怎么办 自己有房怎么办居住证 性格懒散不工作怎么办 脚受凉脚后跟疼怎么办 月子里脚着凉怎么办 腿着凉了疼怎么办 没有土地的农民怎么办 手机屁股坏了怎么办 包颈手术后睡中会勃起怎么办 武警义务兵训练不合格怎么办 空姐体检心率不齐怎么办 空姐体检差身高怎么办 锻炼过猛肌肉疼怎么办 中考体检有问题怎么办 想参军视力不够怎么办 公司体检查出乙肝怎么办 乙肝携带者福利体检怎么办 小孩没考好我该怎么办 客户考虑我该怎么办 明天中考 我该怎么办 考试考差了怎么办 没考上理想高中怎么办 我是差学生中考怎么办 衬衫后背鼓起来怎么办 高考体检表没了怎么办 高考体检视力不合格怎么办 高考体检转氨酶高怎么办 高考体检肝功能异常怎么办 高考体检有乙肝怎么办 高考体检有纹身怎么办 学校体检血压高怎么办 高考体检不属实怎么办 艺考身上有花臂怎么办 义务兵因病致残怎么办 新兵练成绩优秀怎么办 阿提拉部队得了瘟疫怎么办