大数据开发学习笔记

文章目录

1. 虚拟机系统环境搭建

1.1 安装配置

软件安装:oracle vm virtual

插件安装:Vscode中Markdown插件下载:Markdown All in One、Markdown Preview Enhanced(为了使视图看起来比较舒服),Markdown Image(为了使插入截图更加方便)
在这里插入图片描述

下载好之后,打开VirtualBox,点击“新建”,按如下图填入内容:

在这里插入图片描述

分别对系统、存储和网络进行修改

在这里插入图片描述

系统内存大小可以设置的大一点,此处设置成4096MB

在这里插入图片描述

处理器栏可以多设置几个处理器,比如:两个或者两个以上

在这里插入图片描述

存储处的控制器下载并选择老师ftp上的iso文件就好了

网络的话如果为学校的电脑就使用“桥接网络”,如果是自己的电脑,选择NAT网络连接方式

在这里插入图片描述

设置好之后就可以启动了

1.2 设置网络

打开虚拟机后,打开终端,输入 ping 网址,比如:ping www.baidu.com,如果显示如下:
在这里插入图片描述

则网络连接成功,虚拟机初步安装成功。

1.3 安装增强设备

在virtualbox菜单->设备-> 安装增强功能
若安装出错,应为没有gcc的build工具,要先安装build工具:sudo apt install build-essential

在这里插入图片描述

安装完成后,再安装增强功能,需要手动启动安装,在安装目录下打开终端,执行:./autorun.sh

在这里插入图片描述

安装增强功能后,可以设置剪切板共享和文件共享,而且显示页面也可以自动调整。

在这里插入图片描述

1.3 vim编辑器的使用

安装vim编辑器:sudo apt install vim
vi有三种模式:命令、底行命令、编辑。
进入时是命令模式,可以执行命令,例如:按i可以进入编辑模式;编辑模式下按esc键进入命令模式;在命令模式下按:键进入底行命令。

在这里插入图片描述在这里插入图片描述

1.4 修改计算机名

临时修改:hostname 计算机名
永久修改命令:vim /etc/hostname,将文件内容改成计算机名,重启生效。
修改是为了:hadoop集群中需要计算机名与域名一致。

在这里插入图片描述

1.5 配置Java

1.5.1 下载并解压缩安装包

下载java,解压缩(可以双击解压缩)。
命令:tar-xxvf 压缩包名
在这里插入图片描述在这里插入图片描述
在这里插入图片描述

验证软件可用性:在该java解压目录下执行 用cd跳转到该目录,执行./java -version,如果可以显示java的版本说明正常。

在这里插入图片描述

1.5.2 配置路径

路径配置在 .bashrc 中。编辑 .bashrc: hadoop集群需要JAVA_HOME变量,在文件末尾添加

在这里插入图片描述
在这里插入图片描述

1.6 安装salve节点

slave节点使用ubantu的server版,目的是减少系统消耗。

1.7 网络结构选择

1.7.1 分组

使用桥接网络

1.7.2 单机运行三个虚拟节点

由于实验室不能为每台虚拟机提供一个ip地址,所以使用NAT模式

集群中的计算机必须使用固定的ip,首先需要设置NAT网络地址
点击“全局设定”,找到网络设置,点击右侧加号“+”。添加新的NAT网络:进入编辑页面:
注意界面网络地址。
注意区分启动前和启动后看是否可以上网

2. Hadoop集群

2.1 spark、Hadoop版本选择

首先选择Spark版本,访问http://spark.apache.org进入download
选择版本3.1.2,对应hadoop版本是3.2

在这里插入图片描述

java版本:java8

在这里插入图片描述

2.2 软件安装方式

安装方式:Java、spark、hadoop采用下载二进制压缩包、解压缩、配置环境变量方式。
其他软件使用apt安装

2.3 Hadoop集群域名配置

要求域名与计算机名相同。
实例集群需要三个节点:一个namenode、两个datanode。
域名(计算机名使用):master、slave0、slave1,可以不使用这三个,但要与配置文件对应

2.3.1 修改计算机名

单干:将三个计算机修改为master、slave0、slave1。并设置固定的ip地址。永久修改计算机名 命令:sudo vim/etc/hostname
将hostname中的内容修改为需要的计算机名

2.3.2 配置域名

域名文件 /etc/hosts
命令:sudo vim /ect/hosts

在这里插入图片描述

将域名写入文件

在这里插入图片描述

2.3.3 检查ssh联通情况

  • 安装ssh客户端和server端软件:

    命令:sudo apt install openssh-client ,

    ​ sudo apt install openssh-server

    在这里插入图片描述

  • 检查ssh联通情况

    • a)从master节点,ssh所有节点
    • b)从slave0节点,ssh所有节点
    • c)从slave1节点,ssh所有节点
  • ssh免密配置

    • 1)产生密钥;2)传送密钥到集群所有节点。
      从master节点开始:

    • 2)产生密钥,命令:ssh-keygen -t rsa
      提示:一路回车到最后,

    • 3)传送密钥到集群所有节点:
      ssh-copy-id master
      ssh-copy-id slave0
      ssh-copy-id slave1

在这里插入图片描述

  • 验证

    • 验证成功:ssh 名字(master、slave1、slave0)测试一下,看是否需要密码

    在这里插入图片描述

2.3.4 java安装配置

采用当前下载的jdk包配置路径方式,检查java能否正常运行

2.3.5 hadoop软件安装配置

采用下载二进制包配置路径方式安装。
解压缩: tar -zxvf hadoop-3.2.2.tar.gz 或者 直接双击解压缩
解压缩后验证软件的运行:
在这里插入图片描述

配置路径:编辑 .bashrc,添加路径(PATH)
配置之前:

在这里插入图片描述

配置中完成:

在这里插入图片描述

在这里插入图片描述

2.3.6 Hadoop软件配置

配置文件路径:/home/bigdata3/桌面/hadoop-3.2.2/etc/hadoop

1、节点配置:

namenode节点当前域名是master,datanode节点当前域名是slave 0、slave1

在这里插入图片描述

目前配置的路径有(我此时虚拟机设置为中文版,所以路径中有中文):
export JAVA_HOME=/主目录/bigdata3/桌面/jdk1.8

export PATH=/主目录/bigdata3/桌面/jdk1.8/bin:$PATH

export HADOOP_HOME=/主目录/bigdata3/桌面/hadoop-3.2.2

export PATH=/主目录/bigdata3/桌面/hadoop-3.2.2/sbin:/主目录/bigdata3/桌面/hadoop-3.2.2/bin:$PATH

datanode节点配置文件works

datanode节点的配置的域名,一般是一个域名一行。

2、核心配置文件core-site.xml

配置内容:

在这里插入图片描述

3、环境配置文件 hadoop-env.sh

配置java根目录,确保hadoop能找到Java,
配置pid目录:

在这里插入图片描述

4.配置hdfs参数 hdfs-site.xml

本文件中最主要的第一个配置,说明集群资源使用yarn

在这里插入图片描述

2.3.7 Hadoop软件启动

1.hdfs分布式文件系统格式化

hdfs格式化只能进行一次,格式化时如果发现有原来的数据存在,将进入安全模式,以保护现有数据。格式化前,检查是否有数据:按照配置文件core-site.xml,检查是否存在相应目录,如果存在,决定是否格式化,如果继续格式化,需要删除节点。
hdfs格式化只能在namenode节点上进行。
命令:hadoop namenode -format

在这里插入图片描述

2.启动集群

在namenode上执行命令:start-all.sh

在这里插入图片描述

首先检查jps进程:
检查web页面:

在这里插入图片描述

2.4 hdfs的使用

注意:远程集群的使用(如果自己的集群没有启动就使用老师的远程集群)

2.4.1 本地不配置

本地不配置直接使用:需要hdfs的完整URI:hdfs://namenode:port/路径

例如:hadoop fs -mkdir hdfs:172.21.5.156:9000/200110900406

在这里插入图片描述

我的ip:192.168.3.108 用命令行查看:
发挥部分:ip地址可能会出现被其它同学占用或者ip用尽的情况,导致虚拟机无法上网,重新设置一个没有人用的ip就可以了

在这里插入图片描述

2.4.2 本地域名解析

将远程namenode的ip地址,写入本地hosts文件,使用时不需要“hdfs://namenode:port/路径”这部分:

在这里插入图片描述

2.5 集群常见故障

2.5.1 进入安全模式

安全模式是数据保全模式,不允许进入下一步操作,当集群发现数据校验有问题时进入。(生产环境下的严重问题,当前是教学环境)处理方式的退出安全模式停止集群,删除数据文件夹,namenode格式化,再启动集群就可。

2.5.2 丢节点

丢节点知,刚启动时有,启动一阵子就没有了,引起原因有如下:
a.网络情况差
b.配置文件有问题
c.计算机速度与namenode节点比太慢了

2.5.6 与hdfs存储原理冲突

1)文件副本问题:

hdfs是分布式存储,文件默认的block是128MB,原因是大数据环境下,每个文件都很大,要把块分的大一些,提高速度
修改文件副本的方式:修改主机的hadoop配置文件hdfs-site.xml
在values的地方修改节点数,如下:

在这里插入图片描述

2)数据存储位置问题

a) namenode不保存具体数据,保持的是数据信息,主要存储目录:
b)datanode :

  • 小文件(小于一个block的文件):
    前提:文件副本数是1
  • 大文件(大于一个block的文件):
    前提:文件副本数是1
    前提:文件副本数是2

2.6 hdfs命令

1)-mkdir

在hdfs上创建文件夹

2)-ls

查看当前文件夹列表

3)上传文件到hdfs

-copyFromLocal,-put
用法:
hadoop fs -copyFromLocal 本地文件 /hdfs目录
hadoop fs -put 本地文件 /hdfs目录

4)-appendToFile

a.追加本地文件内容到hdfs文件中

b.追加本地文件到hdfs文件中
测试:先上传一个文件到hdfs

在这里插入图片描述

在这里插入图片描述

ab.txt内容

在这里插入图片描述

验证hdfs上ab.txt追加之后的内容:hadoop fs -cat /路径/文件名

追加hdfs文件到hdfs文件中(问号表示不可以,只能从本地文件追加)

6)-cat

显示hdfs文件内容

7)从hdfs拷贝文件到本地

第一种:-copyToLocal
第二种:-get
拷贝一个文件到本地

在这里插入图片描述

不改名拷贝不需要写aFromhdfs.txt 拷贝一个文件夹到本地

在这里插入图片描述

8)-cp是hdfs上的拷贝

a.文件拷贝
原文件

在这里插入图片描述

执行拷贝命令 hadoop fs -cp /200110900406/b.txt /200110900406/b2.txt

拷贝成功:

在这里插入图片描述

b.目录拷贝
原目录:

在这里插入图片描述

执行命令:
hadoop fs -cp /200110900406/ /200110900406_2

拷贝成功:

在这里插入图片描述

9)-df:显示文件hdfs文件系统信息

10)-mkdir:创建目录

11)文件移动

a.本地文件移动到hdfs:-moveFromLocal

b.hdfs移动到本地:-moveToLocal

c.hdfs上的移动:-mv,linux下无改名字这个命令
原目录:

在这里插入图片描述

执行命令:hadoop fs -mv /200110900406_2 /200110900406_3

修改成功

在这里插入图片描述

12)-rmdir

在这里插入图片描述

不能删除非空目录。如果要删除非空目录,需要带参数 --ignore-fail-on-non-empty,错误不显示,但是删不了非空目录,可以创建一个新空目录再删除

为什么删不掉:对数据的目录而言,数据相对安全

12)-rm:删除文件或目录(需要带 -r/-R)都可以

删除文件:

在这里插入图片描述

执行命令:hadoop fs -rm /200110900406/b.txt

删除成功:

在这里插入图片描述

删除目录:
原目录

在这里插入图片描述

执行命令:hadoop fs -rm -r /200110900406_3

删除成功:

在这里插入图片描述

注意:对非空目录删除不提示,对数据安全是不利的,建议删除文件用-rm,删除目录用-rmdir

在这里插入图片描述
在这里插入图片描述

13)-touch:在hdfs上建立文件

在这里插入图片描述
在这里插入图片描述

3. Scala语言

3.1 scala安装

采用下载二进制软件包,解压缩,配置环境变量的方式。
双击解压缩:scala-2.12.15
验证:进入scala目录下的bin目录,执行:./scala

在这里插入图片描述

配置环境变量:vim ./bashrc

在这里插入图片描述

配置好后可直接运行scala

在这里插入图片描述

3.2 scala编程

3.2.1 变量声明

a.一定要使用var或者val

在这里插入图片描述

注:其中var是可变的,val是不可变的

在这里插入图片描述

3.2.2数据类型声明

如果不指定数据类型,系统会自动识别。
指定数据类型的方式: val(var) 变量名:数据类型
注:首字母大写

在这里插入图片描述

String类型是默认导入的java.lang包的内容,可直接使用

3.2.3 算术运算符、关系运算符和逻辑运算符

与其它语言相同
位运算符:计算结果是数字(一般是Int)
位运算与布尔值不可以直接运算

3.2.4 返回值

scala每个语句块都有返回值,返回值是最后一个可执行语句的值。一般不需要用return明确指定。

3.3 使用idea进行scala开发

3.3.1 运行环境搭建

idea安装:下载二进制软件包,解压缩,配置路径
编辑.bashrc,将.bashrc.sh路径添加到PATH

在这里插入图片描述

首先创建一个新项目

在这里插入图片描述

选scala语言,用IDEA进行包管理(手工包管理):

在这里插入图片描述

给项目起名字,检查 scala SDK和JDK是否正确,然后点击“Finish”
按流程建立main程序。
左侧选中src,菜单File->New->Package

在这里插入图片描述

给包取个名字

在这里插入图片描述

一定要选“Object”,对于main所在的对象而言,是一个单例对象

3.3.2 基础语法

  • 一行的写法,多用于赋值,例如:
val resultIf={if(c1>c2) "c1>c2" else "c1<=c2"}
  • for语句
for(变量<-集合){
循环体
}

for也可用于赋值语句。需要使用yield,允许在for循环内进行计算:

在这里插入图片描述

  • if语句

    方式一:

    if(布尔表达式) x else y
    

    方式二:

    if(布尔表达式){
    .......
    }esle{
    ......
    }
    
  • while循环与do while循环

    与其他语言使用方法相同

  • break 和continue

    与其他语言不通,在普通循环for、while、do while中一般不可以使用 。在scala语言中一般用守卫(用if语句来实现断句)来实现

  • scala的集合数据类型

    1.数组:默认为定长数组
    2.使用可变数组需要导入相应的包
    3.遍历数组的编程:

    • a.使用数组的index

    • b.直接遍历

  • Map

    Map映射是键值对的集合
    (“age”->19)+(“age”->24)=(“age”->43)
    注意:只有键相同的才可以相加,并且返回值相加的结果

  • 元组

    用圆括号()包裹数据,数据类型可以不同

在这里插入图片描述

元组中数据的访问形式:
元组名字._index

在这里插入图片描述

元组的嵌套访问(元组内的元组的数据):

在这里插入图片描述

在这里插入图片描述

  • 列表

    集合set的特点是:不包括重复的元素

    发挥部分:Trait特性
    Scala Trait(特征) 相当于 Java 的接口,实际上它比接口还功能强大,与接口不同的是,它还可以定义属性和方法的实现。抽象类和接口的结合,一般情况下Scala的类可以继承多个Trait,从结果来看就是实现了多重继承。Trait的继承用exten关键字继承,多继承时多个Trait之间用with连接,Trait(特征) 定义的方式与类类似,但它使用的关键字是 trait,继承的多个trait中如果有同名的方法和属性,必须要在类中使用“override”重新定义,trait中不可以传参数。
    代码:

trait Read {
 val readType = "Read"
 val gender = "m"
 def read(name:String){
   println(name+" is reading")
 }
}

trait Listen {
 val listenType = "Listen"
 val gender = "m"
 def listen(name:String){
   println(name + " is listenning")
 }
}

class Person() extends Read with Listen{
 override val gender = "f"
}

object test {
 def main(args: Array[String]): Unit = {
   val person = new Person()
   person.read("zhangsan")
   person.listen("lisi")
   println(person.listenType)
   println(person.readType)
   println(person.gender)
   
 }
}

3.3.3 函数式编程

(1)函数的定义:

def 函数名(参数列表):返回值 ={函数体},如果系统可以自动判断出来,可以不写
参数格式: 参数名:类型;如果定义默认参数,直接赋值。标准的用法是,带默认的形参放在默认参数后面。默认参数可以在任意位置,但如果默认参数后有非默认参数,调用时必须带形参名

在这里插入图片描述

(2)匿名形式定义

参数表=>{函数体}
匿名形式定义也可以有名字,将函数赋值给一个变量就可以,例如:
val 变量名=(参数表)=>{函数体}

在这里插入图片描述

(3)高阶函数

高阶函数定义:参数里有函数或返回值是函数

a.参数里有函数

例题:用已定义函数abc完成四则运算

在这里插入图片描述

b.用匿名函数完成四则运算:

当作为函数参数的函数只用一次且书写长度比较短时,一般直接在调用时使用匿名函数

c.函数返回值是函数

例如:用函数返回值是函数的函数计算加减法:(代码如下)

def abc(x:Int):(Int,Int)=>{
if(x>5)(b:Int,a:Int)=>b+a else (b:Int,a:Int)=>b-a
}
val aa=abc(1)
printLn(aa(4,5))
val bb=abc(10)
printLn(bb(4,5))

4.Spark编程

4.1 Spark安装

采用下载二进制软件包,解压缩,配置环境变量的方式。spark是计算框架,集群运行环境可以是hadoop,也可以是spark(生产环境不常用,因为没有分布式文件系统)

双击解压缩:spark-3.1.2-bin-hadoop3.2.tgz
验证:进入spark目录bin下,执行:./spark-shell

在这里插入图片描述

配置环境变量路径PATH:编辑vim .bashrc,添加SPARK_HOME,SCALA_HOME

在这里插入图片描述

4.2 基于RDD的Spark编程

4.2.1 创建RDD

RDD的操作是惰性的,RDD的操作分成两大类:转换类和执行类。
转换类:转换类的操作都是惰性的,只有遇到执行类操作时才执行,之前只是记录操作过程,不执行。
RDD可以执行链式操作,每次转换操作后还是RDD。

(1)从本地文件创建

命令:sc.textFile(URI)

在这里插入图片描述

(2)从hdfs文件创建

命令:sc.textFile(URI)

在这里插入图片描述

(3)从集合数据中创建

命令:sc.parallelize()

在这里插入图片描述

4.2.2 在idea环境下RDD编程环境设置

1)新建一个scala语言项目,用IDEA进行包管理

2)添加spark库到项目中

idea菜单 File->project structure

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

程序:

在这里插入图片描述

4.2.3 RDD的常用转换操作

(1)filter过滤

filter(function),按照function中的规则过滤数据

在这里插入图片描述

用链式写法完成以上程序:

sc.textFile(path="hdfs://192.168.3.108:9000/200110900406/ab.txt").filter(_.contains("c")).foreach(println)

(2)Map(function)

将集合中的每个数据按照function制定的规则进行处理

将_.contains(“c”)和原始数据组合到一起显示:

  • 用map执行加法
  • 用map进行数据的组合操作

4.2.4 分区的概念

发挥部分:RDD是只读的,要想改变RDD中的数据,只能在现有的RDD基础上创建新的RDD;由一个RDD转换到另一个RDD,可以通过丰富的操作算子(map、filter、union、join、reduceByKey… …)实现,不再像MR那样只能写map和reduce了。

创建RDD时指定分区数的方法:textFile的第二个参数。如下程序指定最少三个分区:

val conf =new SparkConf().setAppName("hhh").setMaster("local[*]")
val sc=new SparkContext(conf)
val myRdd=sc.textFile(path = "file:///home/bigdata3/a.txt",minPartitions = 3)
val out1=myRdd.collect()
out1.foreach(println)
Thread.sleep(1000 * 60 * 5)

在这里插入图片描述
在这里插入图片描述

打开链接:http://192.168.3.108:4040
出现界面:
在这里插入图片描述
在这里插入图片描述

在进行分词时

val out1=myRdd.map(x=>x.split(" ")).collect()
out1.foreach(x=>println(x))

输出的是数据的地址而不是数据
所以需要变换输出语句为:

out1.foreach(x=>x.foreach(x=>println(x)))

或者:

out1.foreach(_.foreach(println))//高级写法

在这里插入图片描述
在这里插入图片描述

4.2.5 重分区

DAG图:

shuffle操作会把DAG图分成不同的stag,每个分区都有shuffle操作

106 ![在这里插入图片描述](https://img-blog.csdnimg.cn/01add64ccf7f4b6a8aefa551f3e8f98b.png#pic_center)

flatMap

代码:

在这里插入图片描述

执行结果:

在这里插入图片描述

验证map和flatMap之间有没有shuffle操作:

结果表明,map和flatMap之间灭有shuffle操作

4.2.6 wordcount程序

思路分析:

(1)首先读入文件内容转换为RDD,再用flatMap进行分词,组成键值对(词,1),进行键值队的加法。

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

标准的写法用链式写法(一句话就行):

val myRdd=sc.textFile(path = "file:///home/bigdata3/a.txt",minPartitions = 3).flatMap(x=>x.split(" ")).map((,1)).reduceByKey(+_).foreach(x=>println(x))

4.3 将local模式转换

4.3.1 修改程序由local转换为cluster模式

(1)修改程序指定的master

将setMaster(“local[*]”)删除,通过命令指定参数运行模式

(2)文件路径不能是本地路径:

  • 输入文件放到hdfs上
  • 输出:如果用print输出,无法直接看到输出结果,要到集群的log文件里查看。程序输出一般建议使用文件形式,存储在hdfs上。

(3)spark程序在集群上的运行模式

有两种模式:

  • client模式:driver运行在提交任务的主机上;
  • cluster模式:driver需要在集群中指定的一台机器运行driver
    并且在运行时通过submit的参数

(4)提交任务的命令:spark-sunmit

打开一个终端创窗口,输入: spark-submit,查看帮助

在这里插入图片描述

4.3.2 options相关操作说明

  • –master MASTER_URL

    集群是standalone模式搭建:spark://host:port;集群是mesos模式搭建:mesos://host:port;集群是yarn模式搭建:yarn。如果没有这个参数,将是local模式。
    不同运行模式,需要对spark进行相应配置。
    以yarn集群配置为例:
    SPARK-CONF_DIR:spark配置文件的路径,默认:${SPARK_HOME}/conf,如果在.bashrc配置了环境变量
    SPARK_HOME,使用默认默认值就可以了。
    HADOOP_CONF_DIR:hadoop配置文件的路径
    YARN_CONF_DIR:yarn的配置路径

  • –delpoy -mode

    指定运行模式:client或者cluster。

  • –class

    要运行哪个class,如果运行的是main所在的class,可以不写此参数。

  • –jar

    运行时所需要的jar包,用逗号分割。

  • –packages

    运行时所需要的package

  • –exclude-packages

    解决依赖冲突的

  • –repositories

    远程库

  • –files

    需要放到executor工作目录下的文件

4.3.3 idea程序打包

(1)修改程序

修改的每一句都建议通过spark-shell先进行验证
删除.setMaster,修改输入为hdfs:

(2)打包配置

菜单 file->project structure->artifacts,点击"+"

在这里插入图片描述

系统自动填入modul名字,选择main class

在这里插入图片描述

点击“OK”

在这里插入图片描述

进行jar包的瘦身,即删除不用的jar包,将除最后一个的以外的jar包全部都删除

在这里插入图片描述

删除后:

在这里插入图片描述

观察jar包名字、路径,然后点击“OK”

(3)打包

菜单->Build->Artifacts

在这里插入图片描述

第一次选择build,第二次选择rebuild/先clear 再build,建立完成提示:

在这里插入图片描述

4.3.4 submit到集群运行

4.3.4.1 client模式

命令: spark-submit
–master yarn
–deploy-mode client demo2.jar
运行之前要求通过本地yarn的配置,能够找到运行yarn的集群,要在hosts中写入远程集群的maste

4.3.4.2 cluster模式

命令:spark-submit
–master yarn
–deploy-mode client demo2.jar
在hosts中配置远程集群的master。

4.4 基础编程操练

4.4.1 main参数传递

新建项目,程序:

在这里插入图片描述

在idea中输入参数:
菜单run-edit configurations:

在这里插入图片描述

输入了参数“123” “456”,参数之间用空格隔开,满足两个参数的条件,所以输出:

在这里插入图片描述

如果不满足两个参数,则控制台输出:program argument error
路径:

在这里插入图片描述

执行成功:

在这里插入图片描述

本地生成文件:out.txt文件夹

在这里插入图片描述

4.4.1 生成spark-submit命令的脚本文件

创建一个文件,并给予可执行权限。例如,创建一个文件,并输入如下:

echo spark-submit start
spark-submit --master yarn --deploy-mode cluster /home/bigdata3/IdeaProjects/11.30/out/artifacts/11_30_jar/11.30.jar "hdfs://192.168.3.89:50070/200110900406/ab.txt" "hdfs://192.168.3.89:50070/200110900406/nov"

保存文件后退出,执行:
chomd +x 文件名
sparkSunmit.sh文件内容:

在这里插入图片描述

执行:

在这里插入图片描述

4.5 电影数据分析实例

4.5.1 找出电影评分前五的电影名

评分在ratings.dat文件中,将ratings.dat读入为RDD,取出MovieId和Rating
各种数据类型:

(1)获取数据

取出文件:

val movie=sc.textFile("file:///home/bigdata3/ml-1m/ratings.dat").map(_.split("::"))

(2)求评分平均值

取出相应的数据组成键值对,Rating数值计算需要进行数据类型转换(此处使用toDouble):
查看前10个数据:movie.take(10)
组成键值对:

val movie2=movie.map(x=>(x(1),x(2))).take(10)1形成键值对:val movie_1=movie.map(x=>(x(1),1)).take(10)

在这里插入图片描述
在这里插入图片描述

正式求得时候,代码:(因为在take的时候会变成array里面的array,由上图所示)

在这里插入图片描述

进行数据类型转换并求总分:

在这里插入图片描述

(3)求评分的数量(每个电影有多少个评分):

在这里插入图片描述

(4)求电影评分平均值

思路:同一个电影的总分/总评分人数
首先,组成键值对,键:电影的MovieId,值:(总评分,评分数);

在这里插入图片描述
在这里插入图片描述

(5)取出平均分前五

  • 第一种方法:需要将MovieId与平均分位置对调,变成(平均分,movieId),然后用sortByKey(false)排序,然后再换回来,变成(movieId,平均分)。

在这里插入图片描述

  • 第二种方法:用sortBy,更加简单,不需要调来调去,sortBy有两个主要参数:用哪个属性排序 和 升序还是降序。

在这里插入图片描述

(6)取出评分平均分前五的电影名

  • 第一步:把电影名加入数据集,用join(movieId,(Title,平均分))
  • 第二步:取出前五的电影名

4.6 Spark Dataframe分析

4.6.1 创建入口点

在这里插入图片描述

代码:

val spark = SparkSession.builder().master("local[*]").appName("sparkSQL1")
.config("spark.some.config.option", "some-value").getOrCreate()

4.6.2 创建一个Dataframe

DataFrame:导带有schame信息的RDD,数据既可以来自RDD,也可以来自Hive,HDFS等外部数据库,还可以时json格式的数据
代码:

val df = spark.read.json("/home/bigdata3/software/spark-3.1.2-bin-hadoop3.2/examples/src/main/resources/people.json")
df.show()

dataframe会显示带有格式的schema,people.json文件的内容

在这里插入图片描述
在这里插入图片描述

4.6.3 schema属性创建顺序

创建的schema属性顺序是按照字母表顺序进行排序的

在这里插入图片描述
在这里插入图片描述

4.6.4 DataFrame执行sql

(1)引入式隐式转换

当前需要将DataFrame当成是架构化数据,才能执行sql,所以需要隐式转换。注意:隐式转换的位置在sparksession入口点创建之后,如下位置:

在这里插入图片描述

(2)显示schema样式位置

df.printSchema()

在这里插入图片描述

生成DataFrame时产生了schema,schema自动识别数据类型,是根据原始数据自动识别的。

(3)DataFrame与关系数据库相同吗?

验证方式:在原始数据中写入两个完全相同的数据,对于关系数据库而言,是不可以的,观察DataFrame:

在这里插入图片描述

两个完全相同的数据都存在,说明与关系数据库是不同的。

(4)select语句与数据库是十分相似的

查询:
语句:

df1.select("gender").show()
df1.select("name","gender").show()

结果:

在这里插入图片描述

加“$”的情况,表示将变量代表的数据值取出来:

将查询数据进行计算:

df1.select("name","age"+1).show()

上面这条语句是不可以的,应该使用如下:

df1.select($"name",$"age"+1).show()

在这里插入图片描述
在这里插入图片描述

注意:“$”只是针对数值运算

(5) filter过滤,数值过滤:
df1.filter($“age”>19).show()

(6)groupBy

分组聚合:如果有计算的话,主要针对的是数值属性
注意:null也参与计算

(7)SQL查询编程

首先要创建一个临时表,然后再执行查询。
创建一个临时视图:

注意:下面的py是增强代码块的特性,指代码块是python语法,不同的markdown编辑器对此支持可能会有不同

val df2 = spark.read.json("/home/bigdata3/software/spark-3.1.2-bin-hadoop3.2/examples/src/main/resources/people3.json")
df2.createOrReplaceTempView("people2")
val sqlDF=spark.sql("select * from people2")
sqlDF.show()

结果:

在这里插入图片描述

部分属性的查询:

在这里插入图片描述

语句和sql的一样

4.6.5 创建Dataset

发挥部分:
DataSet补充介绍:
1)DataSet是在Spark1.6中添加的新的接口。
2)与RDD相比,保存了更多的描述信息,概念上等同于关系型数据库中的二维表。
3)与DataFrame相比,保存了类型信息,是强类型的,提供了编译时类型检查。
4)调用Dataset的方法先会生成逻辑计划,然后Spark的优化器进行优化,最终生成物理计划,然后提交到集群中运行。
5)DataSet包含了DataFrame的功能,在Spark2.0中两者得到了统一:DataFrame表示为DataSet[Row],即DataSet的子集。

DataSet实例分析:
(1)首先要创建一个临时视图,再进行查询:

case class Person(name:String,age:Long)
object testDataSet3 {
  def main(args: Array[String]): Unit = {
    val spark=SparkSession.builder().master("local[*]")
      .appName("testDataSet3").config("123","123").getOrCreate()
Person(name:String,age:Long)
    import spark.implicits._
    val caseClassDS=Seq(Person("Andy",32),Person("Tom",20)).toDS()
    caseClassDS.show()
  }

}

运行结果:

在这里插入图片描述

(2)没有定义泛型的DataSet

使用caseclass给予每组数据一个类型

case class Person(name:String,age:Long)
object testDataSet3 {
  def main(args: Array[String]): Unit = {
    val spark=SparkSession.builder().master("local[*]")
      .appName("testDataSet3").config("123","123").getOrCreate()
    import spark.implicits._
    var primitiveDS=Seq(("0",1,2,3),("4",5,6,7),("7",9,8,9)).toDS().show()
  }

系统按照位置自动定义泛型:

在这里插入图片描述

(3)Dataframe转换成DataSet

可以提供一个class将Dataframe转换为DataSet

object testDataSet3 {
  def main(args: Array[String]): Unit = {
    val spark=SparkSession.builder().master("local[*]")
      .appName("testDataSet3").config("123","123").getOrCreate()
    //case class Person(name:String,age:Long)
    import spark.implicits._
    val path1="/home/bigdata3/spark-3.1.2-bin-hadoop3.2/examples/src/main/resources/people.json"
    spark.read.json(path1).as[Person].show()
    var primitiveDS=Seq(("0",1,2,3),("4",5,6,7),("7",9,8,9)).toDS().show()
  }

}

运行结果:

在这里插入图片描述

(4)与RDD的交互操作

通过session创建sc
val sc=spark.sparkContext

A.用反射弧添加schema

通过case class可以将RDD转化为DataFrame

object testDataSet3 {
  def main(args: Array[String]): Unit = {
    val spark=SparkSession.builder().master("local[*]")
      .appName("testDataSet3").config("123","123").getOrCreate()
    import spark.implicits._
    val sc=spark.sparkContext //生成sparkContext,为读取txt文件
    val path1="/home/bigdata3/spark-3.1.2-bin-hadoop3.2/examples/src/main/resources/people.txt"
    val peopleDF=sc.textFile(path1)//读取文件
    ‘’.map(x=>x.split(","))//将数据分开
    .map(x=>Person(x(0),x(1).trim.toInt))//用得到的数据生成Person对象
    .toDF()//转化为Dastaframe
    peopleDF.show()
    peopleDF.createOrReplaceTempView("People")//生成临时视图
    val pDF=spark.sql("SELECT name,age from People where age between 13 and 29")//选出数据
    pDF.show()
    pDF.map(x=>("name1:"+x(0))).show()
  }

运行结果:

在这里插入图片描述

B.通过程序添加schema

如果不能通过预先定义case class,class进行到RDD到DataFrame转换,需要通过用以下三步转换成DataFrame:

  • 从原始RDD创建行的RDD;
  • 创建与步骤1中创建的RDD中的Rows结构匹配的StructType表示的模式;
  • 通过SparkSession提供的createDataFrame方法将模式应用于行的RDD。

代码:

object testDataSet3 {
  def main(args: Array[String]): Unit = {
    val spark=SparkSession.builder().master("local[*]")
      .appName("testDataSet3").config("123","123").getOrCreate()
    import spark.implicits._
    val sc=spark.sparkContext
    val path1="/home/bigdata3/spark-3.1.2-bin-hadoop3.2/examples/src/main/resources/people.txt"

    val peopleRDD=sc.textFile(path1)
    val schemeString = "name age"
    val fields=schemeString.split(" ")
      .map(x=>StructField(x,StringType,nullable = true))
    val schema=StructType(fields)
    val rowRDD=peopleRDD.map(_.split(","))
      .map(x=>Row(x(0),x(1).trim))
    val peopleDF = spark.createDataFrame(rowRDD,schema)
    peopleDF.show()
  }

}
  • 3
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值