综合RDD数据操作
-
需求:
统计客户中的5大家族
-
数据源:customers.csv
将该文件上传到HDFS: /input/customer
我们需要统计第三列,姓氏出现频次最多的前五个。
一.基于IDEA构建spark项目
- 新建maven项目
- 把main中的java文件名改成scala
- 添加scala编译工具 File->Project Structure->Libraries->+
1 添加pom.xml依赖
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>org.example</groupId>
<artifactId>day05RDD</artifactId>
<version>1.0-SNAPSHOT</version>
<properties>
<maven.compiler.source>8</maven.compiler.source>
<maven.compiler.target>8</maven.compiler.target>
</properties>
<repositories>
<repository>
<id>ali-maven</id>
<url>http://maven.aliyun.com/nexus/content/groups/public</url>
<releases>
<enabled>true</enabled>
</releases>
<snapshots>
<enabled>true</enabled>
<updatePolicy>always</updatePolicy>
<checksumPolicy>fail</checksumPolicy>
</snapshots>
</repository>
<repository>
<id>central</id>
<name>Maven Repository Switchboard</name>
<layout>default</layout>
<url>http://repo1.maven.org/maven2</url>
<snapshots>
<enabled>false</enabled>
</snapshots>
</repository>
</repositories>
<dependencies>
<dependency>
<groupId>org.apache.spark</groupId>
<artifactId>spark-core_2.12</artifactId>
<version>3.0.0</version>
</dependency>
<dependency>
<groupId>org.apache.spark</groupId>
<artifactId>spark-sql_2.12</artifactId>
<version>3.0.0</version>
</dependency>
<!--streaming-->
<dependency>
<groupId>org.apache.spark</groupId>
<artifactId>spark-streaming_2.12</artifactId>
<version>3.0.0</version>
</dependency>
<!-- MySQL驱动 -->
<!-- https://mvnrepository.com/artifact/mysql/mysql-connector-java -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.18</version>
</dependency>
</dependencies>
</project>
demo测试
package cn.com.chinahitech
import org.apache.log4j.{Level, Logger}
import org.apache.spark.sql.SparkSession
/**
* @author SJ
* @date 2021/2/1
*/
object Hello {
def main(args: Array[String]): Unit = {
//配置日志显示级别,进行日志的过滤
Logger.getLogger("org").setLevel(Level.ERROR)
// 1 创建spark
val spark = SparkSession.builder().master("local[2]").appName("Hello").getOrCreate()//得到一个spark对象
val sc=spark.sparkContext
// 2 创建RDD数据集
val rdd=sc.parallelize(1 to 9)
// 3 进行转换,行动操作
rdd.map(data => data*2).collect().foreach(println(_))
}
}
2.编程实现
统计五大家族,最终结果存到mysql里
数据集的端口
9870是web网页的访问地址 在hdfs-site.xml这个文件里配置的,默认端口是50070 ,9870是我们自己后改的
package cn.com.chinahitech
import org.apache.log4j.{Level, Logger}
import org.apache.spark.sql.SparkSession
/**
* @author SJ
* @date 2021/2/1
*/
object CustomerAnalysis {
def main(args: Array[String]): Unit = {
//配置日志显示级别,进行日志的过滤
Logger.getLogger("org").setLevel(Level.ERROR)
// 1 创建spark
val spark = SparkSession.builder().master("local[2]").appName("Hello").getOrCreate()//得到一个spark对象
val sc=spark.sparkContext
//从hdfs里加载数据
val customerRDD = sc.textFile("hdfs://192.168.0.104:9000/input/customer/customers.csv")
//看一下是否成功
customerRDD.take(3).foreach(println(_))
}
}
数据出来了,证明数据访问是没有问题的
现在得到的数据每一行是个字符串,字符串之间用逗号分隔,我们需要提取第三列,就是姓氏这一列,并且每一列都用双引号包起来了,需要把双引号去掉,再进行规约。
//3对源数据集进行处理
val tempRDD=customerRDD.map(line=>line.split(","))//每一行的string就变成了Array[String]
//提取数组的第二个值
tempRDD.map(arr=>arr(2))
合起来就是(算子喜欢垂直摆放)
//3对源数据集进行处理
val tempRDD=customerRDD
.map(line=>line.split(","))//每一行的string就变成了Array[String]
.map(arr=>arr(2)) //Array[String]=>姓氏
//看一下
tempRDD.take(3).foreach(println(_))
把双引号去掉
//3对源数据集进行处理
val tempRDD=customerRDD
.map(line=>line.split(","))//每一行的string就变成了Array[String]
.map(arr=>arr(2).replace("\"","")) //Array[String]=>姓氏,并把双引号替换成空
然后进行转换
//3对源数据集进行处理
val tempRDD=customerRDD
.map(line=>line.split(","))//每一行的string就变成了Array[String]
.map(arr=>arr(2).replace("\"","")) //Array[String]=>姓氏,并把双引号替换成空
.map(word=>(word,1))
.reduceByKey(_+_) //规约
//4 进行数据位置交换、排序
val resultRDD=tempRDD.map(data=>data.swap) ////(姓氏,数量) => (数量,姓氏)
.sortByKey(false)//降序排列
.map(data=>data.swap) // //(数量,姓氏)=>(姓氏,数量)
CREATE TABLE `customer` (
`name` varchar(255) NOT NULL,
`count` int DEFAULT NULL,
PRIMARY KEY (`name`)
) ENGINE=MyISAM AUTO_INCREMENT=6 DEFAULT CHARSET=utf8;
mysql建表用来存数据
出现问题:
解决:case class People(name : String, age : Int) 的定义需要放在方法的作用域之外(即Java的成员变量位置)
//5 将RDD转换成DataFrame类型(包含数据+数据的格式)DataFrame=RDD+Schema
//首先要导一个包
import spark.implicits._
//我们现在得到的RDD是这种格式(String,int),我们要把这种数据转换成带有格式的
//这个时候就要借助样例类,样例类存在的意义就是实现数据格式的封装转换
//[样例类定义在方法之外]
val resultDF=resultRDD.map(data=>Customer(data._1,data._2)).toDF()
//查看数据集格式
resultDF.printSchema()
//查看数据,默认显示20条
resultDF.show()
//再写一个成员方法实现把dataframe保存到mysql里的功能
/**
* 给一个数据集df,放到tablename表里面,执行完毕后输出msg消息
* @param df:需要存储的DataFrame数据集
* @param tableName:需要存储到的mysql的表名
* @param msg:执行存储完毕后的输出消息
*/
def saveToMySQL(df: DataFrame,tableName:String,msg:String):Unit={
val url="jdbc:mysql://192.168.0.104:3306/customerdb?characterEncoding=utf8&serverTimezone=Asia/Shanghai&useSSL=false"
val props = new java.util.Properties()
props.put("user","root")
props.put("password","ROOTroot_1")
props.put("driver","com.mysql.cj.jdbc.Driver")
//执行写入
//模式有overwrite、append
df.repartition(1).write.mode("overwrite").jdbc(url,tableName,props)
//输出提示信息
println(msg)
}
在main函数里调用
//6 执行存储到mysql
saveToMySQL(resultDF,"customer","写入成功!")
二.打包上传jar到Linux
把上面的表删掉
1.
清楚非必要依赖,留这一个
3.编译项目, 生成字节码
4.打作业包
三 上传并执行
[hadoop@hadoop01 ~]$ cd /opt/data/
[hadoop@hadoop01 data]$ ll
总用量 37820
drwxrwxr-x 4 hadoop hadoop 173 1月 26 14:09 1_22
-rw-rw-r-- 1 hadoop hadoop 34723590 1月 22 22:22 bjmarket-0.0.1-SNAPSHOT.jar
-rw-rw-r-- 1 hadoop hadoop 1177355 1月 31 20:13 customers.csv
-rw-rw-r-- 1 hadoop hadoop 2358298 2月 1 21:34 day05RDD.jar
drwxrwxr-x 2 hadoop hadoop 87 1月 26 20:55 film_rating
drwxrwxr-x 2 hadoop hadoop 202 1月 26 13:26 hive_dir
-rw-rw-r-- 1 hadoop hadoop 8857 1月 22 13:39 market.sql
-rw------- 1 hadoop hadoop 7257 1月 22 22:56 nohup.out
-rw-rw-r-- 1 hadoop hadoop 439966 1月 21 21:01 world.sql
[hadoop@hadoop01 data]$ spark-submit day05RDD.jar #执行
21/02/01 21:38:40 WARN NativeCodeLoader: Unable to load native-hadoop library for your platform... using builtin-java classes where applicable
写入成功!
[hadoop@hadoop01 data]$
也可以像老师这样指定主类执行、指定cpu和内存
对于这个报错
是配置问题
配置完重启电脑就行