大数据之路系列之SPARK2-spark提升(09)

大数据之路系列之SPARK2-spark提升(09)


一、宽依赖和窄依赖

在这里插入图片描述
窄依赖:指的是RDD的每个partition分区只被子RDD的一个partition分区使用,例如map、filter等算子,一对一的关系
宽依赖:父RDD的每个分区都可能被子RDD的多个分区使用,例如groupByKey、reduceByKey、sortBykey等这些都会产生shuffle操作;父partition中的数据会传输到多个partition中。

二、stage

spark job是根据action算子触发的,遇到action算子就会起一个job
spark Job会被划分为多个stage,每一个stage都是一组并行的task组成的
提示:stage的划分依据就是是否产生shuffle(宽依赖),遇到shuffle操作就划分成前后两个stage
提示:stage是由一组并行task组成,stage会将一批task用taskSet来封装,提交给TaskScheduler进行分配,最后发送到executor执行
在这里插入图片描述
提示:stage的划分规则:从后往前,遇到宽依赖就划分stage

为什么是从后往前呢?因为RDD之间是有血缘关系的,后面的RDD依赖前面的RDD,也就是说后面的RDD要等前面的RDD执行完,才会执行。
所以从后往前遇到宽依赖就划分为两个stage,shuffle前一个,shuffle后一个。如果整个过程没有产生shuffle那就只会有一个stage

看这个图
RDD G 往前推,到RDD B的时候,是窄依赖,所以不切分Stage,再往前到RDD A,此时产生了宽依赖,所以RDD A属于一个Stage、RDD B 和 G属于一个Stage

再看下面,RDD G到RDD F,产生了宽依赖,所以RDD F属于一个Stage,因为RDD F和 RDD C、D、E这几个RDD没有产生宽依赖,都是窄依赖,所以他们属于一个Stage。

所以这个图中,RDD A 单独一个stage1,RDD C、D、E、F被划分在stage2中,
最后RDD B和RDD G划分在了stage3 里面.

注意:Stage划分是从后往前划分,但是stage执行时从前往后的,这就是为什么后面先切割的stage为什么编号是3.

三、Spark Job的三种提交模式

第一种,standalone模式,基于Spark自己的standalone集群。指定–master spark://bigdata01:7077

第二种,是基于YARN的client模式。
指定–master yarn --deploy-mode client
这种方式主要用于测试,查看日志方便一些,部分日志会直接打印到控制台上面,因为driver进程运行在本地客户端,就是提交Spark任务的那个客户端机器,driver负责调度job,会与yarn集群产生大量的通信,一般情况下Spark客户端机器和Hadoop集群的机器是无法内网通信,只能通过外网,这样在大量通信的情况下会影响通信效率,并且当我们执行一些action操作的时候数据也会返回给driver端,driver端机器的配置一般都不高,可能会导致内存溢出等问题。

第三种,是基于YARN的cluster模式。【推荐】
指定–master yarn --deploy-mode cluster
这种方式driver进程运行在集群中的某一台机器上,这样集群内部节点之间通信是可以通过内网通信的,并且集群内的机器的配置也会比普通的客户端机器配置高,所以就不存在yarn-client模式的一些问题了,只不过这个时候查看日志只能到集群上面看,这倒没什么影响。
在这里插入图片描述

四、shuffle机制分析

五、checkpoint概述

对重要RDD进行剪出,实现容错和高可用

使用方法

//1:设置checkpint目录
sc.setCheckpointDir("hdfs://xx:9000/chk001")
 //2:对rdd执行磁盘持久化
dataRDD.persist(StorageLevel.DISK_ONLY)
//3:对rdd执行checkpoint操作
dataRDD.checkpoint()
  

在执行checkpoint前需要先执行下基于磁盘的持久化,原因是如果没有持久化,checkpoint的时候也会重新计算RDD数据,所以持久化以后就不需要重复计算一次了,效率高

六、checkpoint和持久化的区别

1.linage血缘是否发生变化

checkpoint会斩断血缘,持久化血缘关系还在

2.丢失数据的可能性

持久化丢失数据的可能性比较大,checkpoint的存储地址通常是hdfs,丢失的可能比较小

七、spark性能优化

spark优化主要是内存优化

内存都哪去了

Java的对象的对象头已经元数据信息都会额外的占用空间,导致原始数据执行中会变大

如何预计需要多少内存呢?

val cache: Long=sc.textFile("C:\\project\\db_spark\\src\\main\\resources\\dim_product.txt").cache().count()

性能优化方案

1.高性能序列化类库

如果此对象可以支持序列化,则将其实现Serializable接口,让它支持序列化,优点:方便,缺点 空间大速度慢

Kryo序列化机制:Spark也支持使用Kryo序列化。Kryo序列化机制比Java序列化机制更快,而且序列化后的数据占用的空间更小,通常比Java序列化的数据占用的空间要小10倍左右。适合自定义对象

package com.imooc.java;

import com.esotericsoftware.kryo.Kryo;
import org.apache.spark.SparkConf;
import org.apache.spark.api.java.JavaRDD;
import org.apache.spark.api.java.JavaSparkContext;
import org.apache.spark.api.java.function.FlatMapFunction;
import org.apache.spark.api.java.function.Function;
import org.apache.spark.api.java.function.VoidFunction;
import org.apache.spark.serializer.KryoRegistrator;
import org.apache.spark.storage.StorageLevel;

import java.io.Serializable;
import java.util.Arrays;
import java.util.Iterator;

/**
 * 需求:Kryo序列化的使用
 */
public class KryoSerjava {
    public static void main(String[] args) {
        //创建SparkContext:
        SparkConf conf = new SparkConf();
        conf.setAppName("KryoSerjava")
                .setMaster("local")
                .set("spark.serializer", "org.apache.spark.serializer.KryoSerializer")
                .set("spark.kryo.classesToRegister", "com.imooc.java.Person");
        JavaSparkContext sc = new JavaSparkContext(conf);

        JavaRDD<String> dataRDD = sc.parallelize(Arrays.asList("hello you", "hello me"));
        JavaRDD<String> wordsRDD = dataRDD.flatMap(new FlatMapFunction<String, String>() {
            @Override
            public Iterator<String> call(String line) throws Exception {
                return Arrays.asList(line.split(" ")).iterator();
            }
        });
        JavaRDD<Person> personRDD = wordsRDD.map(new Function<String, Person>() {
            @Override
            public Person call(String word) throws Exception {
                return new Person(word, 18);
            }
        }).persist(StorageLevel.MEMORY_ONLY_SER());

        personRDD.foreach(new VoidFunction<Person>() {
            @Override
            public void call(Person person) throws Exception {
                System.out.println(person);
            }
        });

        while (true){
            ;
        }

    }
}
class Person implements Serializable{
    private String name;
    private int age;
    Person(String name,int age){
        this.name = name;
        this.age = age;
    }

    @Override
    public String toString() {
        return "Person{" +
                "name='" + name + '\'' +
                ", age=" + age +
                '}';
    }
}

2.持久化或者checkpoint

3.JVM垃圾回收调优

八、SparkSQL 集成 Hive

1.在spark_sql命令行中集成hive

(1)修改日志的格式

mv log4j.properties.template log4j.properties
info ->error

(2) hive-site.xml 保留核心配置

<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<?xml-stylesheet type="text/xsl" href="configuration.xsl"?>
<configuration>
  <!-- 指定Hive默认在HDFS中的数据存储目录 -->
  <property>
    <name>hive.metastore.warehouse.dir</name>
    <value>/user/hive/warehouse</value>
    <description>location of default database for the warehouse</description>
  </property>
  <!-- 指定Hive的MetaStore(MySQL的URL信息) -->
  <property>
    <name>javax.jdo.option.ConnectionURL</name>
    <value>jdbc:mysql://192.168.182.1:3306/hive?serverTimezone=Asia/Shanghai</value>
  </property> 
  <!-- 指定MySQL的驱动类名 -->  
  <property>
    <name>javax.jdo.option.ConnectionDriverName</name>
    <value>com.mysql.cj.jdbc.Driver</value>
  </property>
  <!-- 指定MySQL的用户名 -->
  <property>
    <name>javax.jdo.option.ConnectionUserName</name>
    <value>root</value>
  </property>
  <!-- 指定MySQL的密码 -->
  <property>
    <name>javax.jdo.option.ConnectionPassword</name>
    <value>admin</value>
  </property>
</configuration>

(3)MySQLjar包导入到spark的目录中

hive/lib ->spark/hars

(4)启动spark-sql

bin/spark-sql --master yarn

2.在spark代码中集成hive

(1) 添加hive-site.xml

(2)添加pom依赖

<dependency>
	<groupId>org.apache.spark</groupId>
	<artifactId>spark-hive_2.12</artifactId>
	<version>3.2.1</version>
</dependency>
<dependency>
	<groupId>mysql</groupId>
	<artifactId>mysql-connector-java</artifactId>
	<version>8.0.16</version>
</dependency>

(3)代码

SparkSession ss = SparkSession.builder().config(sparkConf).appName("sparkSql").master("local").enableHiveSupport().getOrCreate();

3.SparkSQL写入Hive表的几种方式

(1)第一个:使用inserInto()方法。

(2)第二个:使用saveAsTable()方法。

(3)第三个:使用SparkSQL语句。

最常用的方法

  ss.sql("  insert into itag.t_commodity_cate_bak select * from itag.t_commodity_cate");
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

居高声自远,非是藉秋风

千山万水总是情,赏个一块行不行

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值