经过前期的了解和项目搭建,相信大家最关心的是能不能跑个demo出来,基于一些常见的需求场景,来跑一波数据分析,这样学习才能有继续的动力。因此后续也不会有先去看它的代码实现原理啥的,还是那句话,现在这个阶段如果一头扎进去,出不来的。
数据准备:
网站埋点数据。
需求:后台运营想知道我们当前哪些的访问量是最高的,基于火爆商品的访问做一些运营活动。
需求分析:我们要基于埋点数据找到包含商品访问的记录,解析数据成<K,V> K为商品Id,V为次数。然后排序取Top10或者Top20等等
数据存储:
当前数据还是存储在mysql(后期迁移到hive内)
代码环境:
基于前面的环境的项目结构做编码
import org.apache.spark.SparkConf
import org.apache.spark.rdd.RDD
import org.apache.spark.sql.{DataFrame, SparkSession}
/**
*
* 贴出的是样例代码,因为不同的数据源读取方式不一样,但是思路是一样的
*
*/
object SparkSqlGetMysqlTest {
def main(args: Array[String]): Unit = {
var sc = new SparkConf()
.setMaster("local")
.setAppName("分区读取Mysql")
val spark = SparkSession.builder().config(sc).getOrCreate()
val dataFromMysql: DataFrame = spark.read
.format("jdbc")
.option("url", "jdbc:mysql")
.option("driver", "com.mysql.jdbc.Driver")
.option("dbtable", "MYSQL_DB")
.option("user", "xxxx")
.option("password", "xxxx")
.option("partitionColumn", "ID")
.option("lowerBound", "0")
.option("upperBound", "500000")
.option("numPartitions", "20")
.load()
dataFromMysql.createOrReplaceTempView("MYSQL_DB_TEMP")
val goods = spark.sql("取出属于商品详情页访问的那一条数据,和写sql类似")
val allGoods: RDD[(String, Int)] = goods.rdd
//过滤条件
.filter(s=> s.getString(0).contains("/p/"))
//加工数据,做一些数据修正或者数据格式规范化操作
.map(record => record.getString(0).replace("v", "V").replace("HTML", "html"))
//最终加工成<K,V>(思路来源于Spark的文字统计)
.map(record => (record.substring(1,7), 1))
//reduceByKey 统计某个sku的访问量<sku,数量>
val result = allSkuCount.reduceByKey(_ + _)
//倒序排 取出top10
val top10 = result.sortBy(_._2, false).take(20)
top10.foreach(println)
}
}
partitionColumn(数据库内用于读取区分的Id);
lowerBound(下界);
upperBound(上界);
numPartitions(分区数量);
这是Spark读取mysq分区读取的方式,分区的方式是定出当前多少个partion,每个partion内读取哪些数据。
例如当前我的数据库内有56万的数据。。upperBound = 500000 ,lowerBound =0 , numPartitions = 20,partitionColumn = Id用的是主键
读取的格式就是如下:
[1]. Id < 25000
[2]. 25000<=id<50000
[3]. 50000<=id<75000
[4]. …
…
…
…
[20]. 500000<=id
这样一来,每个分区的数量差不多是均衡的(但是这边有个问题我没有去研究,那就是随着数据量的提升,这边的分区方式是动态在变?还是怎么配置,没有想好)。
数据输出格式
(100001,10000)
(100002,6000)
(300001,4000)
(400001,3900)
(104001,1000)
标识就是每个商品被访问的总量倒叙排列
关于分区读取的,可以写个小栗子看它是怎么读取。
def main(args: Array[String]): Unit = {
var sc = new SparkConf()
.setMaster("spark://192.168.2.142:7077")
// .setMaster("local")
.setAppName("分区读取Mysql")
val spark = SparkSession.builder().config(sc).getOrCreate()
val dataFromMysql : DataFrame= spark.read
.format("jdbc")
.option("url", "jdbc:mysql")
.option("driver", "com.mysql.jdbc.Driver")
.option("dbtable", "MYSQL_DB")
.option("user", "xxxx")
.option("password", "xxxx")
.option("partitionColumn","ID")
.option("lowerBound","0")
.option("upperBound","500000")
.option("numPartitions","20")
.load()
dataFromMysql.rdd.saveAsTextFile("file:///usr/local/bigdata/output.txt")