场景一:使用Spark RDD实现单词计数
代码如下:
package org.jy.data.yh.bigdata.drools.scala.sparkrdd
import org.apache.spark.SparkConf
import org.apache.spark.SparkContext
import org.apache.spark.rdd.RDD
/**
* Spark RDD统计单词
*/
object SparkRDDWordCountFrep {
def main(args: Array[String]): Unit = {
// 创建SparkConf对象,存储应用程序的配置信息
val conf = new SparkConf()
// 设置应用程序名称,可以在Spark Web UI中显示的名称
conf.setAppName("SparkRDD-WordCount")
// 设置集群Master节点访问地址
conf.setMaster("spark://centoshadoop1:7077")
// 创建SparkContext对象,该对象是提交Spark应用程序的入口
val sc = new SparkContext(conf);
// 读取指定路径(取程序执行时传入的第一个参数)中的文件内容,生成一个RDD集合
val linesRDD:RDD[String] = sc.textFile(args(0)); // 程序执行的第一个参数 args(0
// 将RDD的每一个元素按照空格进行拆分并将结果合并为一个新的RDD
val wordsRdd:RDD[String] = linesRDD.flatMap(_.split(" ")) // 空格进行拆分
// 将RDD中的每个单词和数字1放到一个元组里,即(word,1)
val paresRDD:RDD[(String,Int)] = wordsRdd.map((_,1)) // map操作
// 对单词根据key进行聚合,对相同的key进行value的累加
val wordCountsRDD:RDD[(String,Int)] = paresRDD.reduceByKey(_+_);
// 按照单词数量降序排列
val wordCountsSortRDD:RDD[(String,Int)] = wordCountsRDD.sortBy(_._2,false);
// 保存结果到指定的路径(取程序执行时传入的第二个参数)
wordCountsSortRDD.saveAsTextFile(args(1))
// 停止SparkContext,结束该任务
sc.stop();
}
}
统计words.txt中单词的数量(mycluster为hadoop集群的逻辑名称)
bin/spark-submit \
--master spark://centoshadoop1:7077 \
--class org.jy.data.yh.bigdata.drools.scala.sparkrdd.SparkRDDWordCountFrep \
/home/hadoop/tools/SSO-Scala-SparkRdd-1.0-SNAPSHOT.jar \
hdfs://mycluster/input/words.txt \
hdfs://mycluster/output
查看统计的结果
hadoop fs -cat /output/*
(Bye,33)
(Hello,22)
(hadoop,22)
(yang,11)
(,11)
(bye,11)
(hong,11)
(world,11)
场景二:使用Spark SQL实现单词计数
代码如下
package org.jy.data.yh.bigdata.drools.scala.sparksql
import org.apache.spark.sql.{DataFrame, Dataset, SparkSession}
/**
* Spark SQL统计单词计数WordCount,数据来源仍然是HDFS中的/input/words.txt
*/
object SparkSQLWordCountFrep {
def main(args:Array[String]):Unit = { // 定义main函数
// 创建SparkSession对象,并设置应用名称,运行模式
val session = SparkSession.builder()
.appName("SparkSQLWordCountFrep") // 设置应用名称,在Spark Web UI界面中展示
.master("spark://centoshadoop1:7077") // spark的集群地址
.getOrCreate()
// 读取HDFS中的单词文件
val lines : Dataset[String] = session.read.textFile("hdfs://mycluster/input/words.txt")
// 导入session对象中的隐式转换
import session.implicits._
// 将Dataset中的数据安装空格进行切分并合并
val words :Dataset[String] = lines.flatMap(_.split(" "))
// 将Dataset中默认的列名value改为word,同时转换为DataFrame
val df: DataFrame = words.withColumnRenamed("value","word")
// 给DataFrame创建临时视图
df.createTempView("v_words")
// 执行SQL,从DataFrame中查询数据,按照单词进行分组
val result:DataFrame = session.sql(
"select word,count(*) as count from v_words group by word order by count desc"
)
// 显示查询结果
result.show()
// 关闭SparkSession
session.close()
}
}
bin/spark-submit --master spark://centoshadoop1:7077 \
--class org.jy.data.yh.bigdata.drools.scala.sparksql.SparkSQLWordCountFrep /home/hadoop/tools/SSO-Scala-SparkSql-1.0-SNAPSHOT.jar
执行结果如下:
+------+-----+
| word|count|
+------+-----+
| Bye| 33|
|hadoop| 23|
| Hello| 22|
| bye| 14|
| | 12|
| world| 12|
| yang| 11|
| hong| 11|
| hello| 1|
+------+-----+
场景三:使用Spark SQL读写MySQL数据库
代码如下:
package org.jy.data.yh.bigdata.drools.scala.sparksql
import org.apache.spark.sql.{Row, SparkSession}
import org.apache.spark.sql.types.{IntegerType, StringType, StructField, StructType}
/**
* 将RDD的计算结果写入到关系数据库中,以便于前端页面展示
* 本例使用Spark SQL将DataFrame中的数据通过JDBC写入到MySQL数据库中
*/
object SparkSQLJDBCToDBMysql {
def main(args:Array[String]):Unit ={
// 创建或者得到SparkSession
val spark = SparkSession.builder()
.appName("通过SparkJDBC把计算的结果写入MySQL")
.getOrCreate()
// 创建存放两条学生信息的RDD
val studentRDD = spark.sparkContext.parallelize(
Array("4 xiaoming 26","5 xiaogang 27") // 各项间以空格分割
).map(_.split(" "))
// 通过StructType指定每个字段的Schema
val schema = StructType(
List( // 指定数据类型
StructField("id",IntegerType,true),
StructField("name",StringType,true),
StructField("age",IntegerType,true)
)
)
// 将studentRDD映射为rowRDD,rowRDD中的每一个元素都为一个Row对象
val rowRDD = studentRDD.map(line=>
Row(line(0).toInt,line(1).trim,line(2).toInt)
)
// 建立rowRDD和Schema之间的对应关系
val studentDF = spark.createDataFrame(rowRDD,schema);
// 将结果追加到MySQL的student表中
studentDF.write.mode("append") // 保存模式为追加,即是在原来的表中追加数据
.format("jdbc")
.option("url","jdbc:mysql://192.168.227.136:3306/spark_db?createDatabaseIfNotExist=true&characterEncoding=UTF-8&useSSL=fals")
.option("driver","com.mysql.jdbc.Driver")
.option("dbtable","student") // 表名
.option("user","root")
.option("password","123456")
.save()
}
}
==============================================================================
create database spark_db;
mysql> use spark_db;
Database changed
mysql> create table student(id int,name varchar(20),age int);
Query OK, 0 rows affected (0.04 sec)
插入三条测试数据
insert into student values(1,'zhangsan',23);
insert into student values(2,'lisi',19);
insert into student values(3,'wangwu',25);
maven打包发布到Spark 集群
bin/spark-submit \
--master spark://centoshadoop1:7077 \
--jars /home/hadoop/tools/mysql-connector-java-5.1.46.jar \
--class org.jy.data.yh.bigdata.drools.scala.sparksql.SparkSQLJDBCToDBMysql \
/home/hadoop/tools/SSO-Scala-SparkSql-1.0-SNAPSHOT.jar
查看数据表student记录:
mysql> select * from student;
+------+----------+------+
| id | name | age |
+------+----------+------+
| 1 | zhangsan | 23 |
| 2 | lisi | 19 |
| 3 | wangwu | 25 |
| 5 | xiaogang | 27 |
| 4 | xiaoming | 26 |
+------+----------+------+
5 rows in set (0.00 sec)