Hello Spark

376 阅读5分钟

image.png #大数据#

What is Spark

历史与简介

  • 2009年,Spark诞生于伯克利大学的AMPLab实验室。最出Spark只是一个实验性的项目,代码量非常少,属于轻量级的框架。
  • 2010年,伯克利大学正式开源了Spark项目。
  • 2013年,Spark成为了Apache基金会下的项目,进入高速发展期。第三方开发者贡献了大量的代码,活跃度非常高。
  • 2014年,Spark以飞快的速度称为了Apache的顶级项目。
  • 2015年~,Spark在国内IT行业变得愈发火爆,大量的公司开始重点部署或者使用Spark来替代MapReduce、Hive、Storm等传统的大数据计算框架。
  • Spark项目的初衷是为了代替MapReduce(MapReuce是一个很重型的计算工具。究其原因,一个是因为MapReduce有大量的磁盘IO(读写电脑磁盘)工作要做,这磁盘IO可以说是相当花时间,再加上一旦把中间结果存储在HDFS文件里面(而不是本地磁盘),上一个节点得花时间去发文件,下一个计算节点也得花时间去做网络请求取数据,难道网络通讯不要时间吗?另一者是因为MapReduce这算法很底层,只提供map和reduce两个操作给你,我们现在经常需要的什么where啊,join啊,全得依靠data shuffle的过程洗出来(data shuffle,广义来说就是在map和reduce之间做的一切事情,例如排序,分片,筛选)),提供一种既可以极大批量的处理分布式的数据,又有足够的容错能力,且上手容易,速度快,可以让人实现实时交互分析的解决方案。(实时交互分析的意思是,在使用正确的方法的前提下,可以马上得到自己需要的分析结果)。

特点

  • 通用:多数据源、应用场景 。
  • 高效:充分利用内存分布式计算 。
  • 易用:多语言、丰富的API。

适用场景

  1. Spark是基于内存的迭代计算框架,适用于需要多次操作特定数据集的应用场合。需要反复操作的次数越多,所需读取的数据量越大,受益越大,数据量小但是计算密集度较大的场合,受益就相对较小。

  2. 由于RDD的特性,Spark不适用那种异步细粒度更新状态的应用,例如web服务的存储或者是增量的web爬虫和索引。就是对于那种增量修改的应用模型不适合。

  3. 数据量不是特别大,但是要求实时统计分析需求。

系统架构

image.png

RDD (Resilient Distributed Dataset) 弹性分布式数据集

  • 弹性-因为Spark RDD的数据大部分情况下是在内存中的,这也是Spark运行速度比MapReduce/ Hive快很多的原因,但在内存资源不足时,它会自动根据资源情况弹性地利用磁盘来保存一小部分 数据。
  • 分布式-在Spark中,对数据的操作无外乎是创建RDD,转换RDD,以及调用RDD的action操作进行 计算。Spark 会自动将RDD中的数据分发到集群的不同节点,并将操作并行化执行。

RDD运行过程

创建/转换RDD → 构建DAG → 划分Stage → 分发到Executor执行。

image.png

Stage的划分

根据RDD分区的依赖关系划分Stage:

  • 在DAG中进行反向解析,遇到宽依赖就断开,遇到窄依赖就把当前的RDD加入到当前Stage中;
  • 将窄依赖尽量划分在同一个Stage中,可以实现流水线计算;

image.png

RDD操作过程

image.png

image.png

Why we use Spark?

Spark VS MR

image.png

丰富的计算因子

                private static void map(){
		SparkConf conf =new SparkConf().setAppName("map").setMaster("local");
		JavaSparkContext sc =new JavaSparkContext(conf);
		List<Integer> numbers = Arrays.asList(1,2,3,4,5);
	    JavaRDD<Integer> numberRDD = sc.parallelize(numbers);
	    JavaRDD<Integer> multipleNumberRDD = numberRDD.map(new Function<Integer,Integer>(){
 
			/**
			 * 
			 */
			private static final long serialVersionUID = 1L;
 
			@Override
			public Integer call(Integer v1) throws Exception {
				// TODO Auto-generated method stub
				return v1*2;
			}
	    });
	    multipleNumberRDD.foreach(new VoidFunction<Integer>() {
			
			/**
			 * 
			 */
			private static final long serialVersionUID = 1L;
 
			@Override
			public void call(Integer t) throws Exception {
				System.out.println(t);
				
			}
		});
		sc.close();
	}
   private static void filter(){
	SparkConf conf =new SparkConf().setAppName("map").setMaster("local");
	JavaSparkContext sc =new JavaSparkContext(conf);
	List<Integer> numbers =Arrays.asList(1,2,3,4,5,6,7,8,9,10);
	JavaRDD<Integer> numberRDD =sc.parallelize(numbers);
	JavaRDD<Integer> evennumberRDD= numberRDD.filter(new Function<Integer, Boolean>() {

		/**
		 * 
		 */
		private static final long serialVersionUID = 1L;

		@Override
		public Boolean call(Integer v1) throws Exception {
			// TODO Auto-generated method stub
			return v1%2==0;
		}
	});
	evennumberRDD.foreach(new VoidFunction<Integer>() {

		/**
		 * 
		 */
		private static final long serialVersionUID = 1L;

		@Override
		public void call(Integer t) throws Exception {
			System.out.println(t);
			
		}
		
	});
	sc.close();
}
    
    
 private static void flatMap(){
		SparkConf conf =new SparkConf().setAppName("flatMap").setMaster("local");
		JavaSparkContext sc =new JavaSparkContext(conf);
		List<String> linelist = Arrays.asList("hello you","hello me","hello world");
		JavaRDD<String> lines = sc.parallelize(linelist);
		JavaRDD<String> words = lines.flatMap(new FlatMapFunction<String,String>() {
 
			@Override
			public Iterator<String> call(String t) throws Exception {
				
				return Arrays.asList(t.split(" ")).iterator();
			}
		});
		words.foreach(new VoidFunction<String>() {
 
			/**
			 * 
			 */
			private static final long serialVersionUID = 1L;
 
			@Override
			public void call(String t) throws Exception {
				System.out.println(t);
				
			}
			
		});
		sc.close();
	}
  private static void groupByKey(){
		SparkConf conf =new SparkConf().setAppName("groupByKey").setMaster("local");
		JavaSparkContext sc =new JavaSparkContext(conf);
		List<Tuple2<String, Integer>> scoreList = Arrays.asList(
				new Tuple2<String, Integer>("class1",80),
				new Tuple2<String, Integer>("class2",75),
				new Tuple2<String, Integer>("class1",90),
				new Tuple2<String, Integer>("class2",65));
		JavaPairRDD<String, Integer> scores = sc.parallelizePairs(scoreList);
		JavaPairRDD<String, Iterable<Integer>> groupScorese=scores.groupByKey();
		groupScorese.foreach(new VoidFunction<Tuple2<String,Iterable<Integer>>>() {
 
			/**
			 * 
			 */
			private static final long serialVersionUID = 1L;
 
			@Override
			public void call(Tuple2<String, Iterable<Integer>> t)
					throws Exception {
				System.out.println("class: " + t._1);
				Iterator<Integer> ite =t._2.iterator();
				while(ite.hasNext()){
					System.out.println(ite.next());
				}
				System.out.println("=====================================");
				
				
			}
			
		});
		
		sc.close();
	}
        
private static void reduceByKey(){
		SparkConf conf =new SparkConf().setAppName("reduceByKey").setMaster("local");
		JavaSparkContext sc =new JavaSparkContext(conf);
		List<Tuple2<String, Integer>> scoreList = Arrays.asList(
				new Tuple2<String, Integer>("class1",80),
				new Tuple2<String, Integer>("class2",75),
				new Tuple2<String, Integer>("class1",90),
				new Tuple2<String, Integer>("class2",65));
		JavaPairRDD<String, Integer> scores = sc.parallelizePairs(scoreList);
		JavaPairRDD<String, Integer> reduceScorese=scores.reduceByKey(new Function2<Integer, Integer, Integer>(){
 
			@Override
			public Integer call(Integer arg0, Integer arg1) throws Exception {
				// TODO Auto-generated method stub
				return arg0+arg1;
			}});
		    reduceScorese.foreach(new VoidFunction<Tuple2<String,Integer>>() {
 
				@Override
				public void call(Tuple2<String, Integer> t) throws Exception {
					System.out.println(t._1+":"+t._2);
					
				}
			});
		
		sc.close();
	}
private static void sortByKey(){
		SparkConf conf =new SparkConf().setAppName("reduceByKey").setMaster("local");
		JavaSparkContext sc =new JavaSparkContext(conf);
		List<Tuple2<Integer, String>> scoreList = Arrays.asList(
				new Tuple2<Integer, String>(65,"ieo"),
				new Tuple2<Integer, String>(50,"tom"),
				new Tuple2<Integer, String>(100,"marry"),
				new Tuple2<Integer, String>(80,"jack"));
 
		JavaPairRDD<Integer, String> scores = sc.parallelizePairs(scoreList);
		JavaPairRDD<Integer,String> sortScores =scores.sortByKey(false);
		sortScores.foreach(new VoidFunction<Tuple2<Integer,String>>(){
 
			@Override
			public void call(Tuple2<Integer, String> t) throws Exception {
				System.out.println(t._1+ ": "+t._2);
				
			}
			
		});
		sc.close();
	}
private static void join(){
		SparkConf conf =new SparkConf().setAppName("reduceByKey").setMaster("local");
		JavaSparkContext sc =new JavaSparkContext(conf);
		List<Tuple2<Integer,String>> studentList =Arrays.asList(
				new Tuple2<Integer,String>(1, "leo"),
				new Tuple2<Integer,String>(2, "jack"),
				new Tuple2<Integer,String>(3, "tom"));
		List<Tuple2<Integer,Integer>> scoreList =Arrays.asList(
				new Tuple2<Integer,Integer>(1, 100),
				new Tuple2<Integer,Integer>(2, 90),
				new Tuple2<Integer,Integer>(3, 60));
		JavaPairRDD<Integer, String> students = sc.parallelizePairs(studentList);
		JavaPairRDD<Integer, Integer> scores = sc.parallelizePairs(scoreList);
		JavaPairRDD<Integer, Tuple2<String, Integer>> studentScores = students.join(scores);
		studentScores.foreach(new VoidFunction<Tuple2<Integer,Tuple2<String,Integer>>>() {
 
			@Override
			public void call(Tuple2<Integer, Tuple2<String, Integer>> t)
					throws Exception {
				System.out.println(t._1+":"+t._2._1+":"+t._2._2);
				
			}
		});
		
		sc.close();
	}

private static void cogroup(){
		SparkConf conf =new SparkConf().setAppName("reduceByKey").setMaster("local");
		JavaSparkContext sc =new JavaSparkContext(conf);
		List<Tuple2<Integer,String>> studentList =Arrays.asList(
				new Tuple2<Integer,String>(1, "leo"),
				new Tuple2<Integer,String>(2, "jack"),
				new Tuple2<Integer,String>(3, "tom"));
		List<Tuple2<Integer,Integer>> scoreList =Arrays.asList(
				new Tuple2<Integer,Integer>(1, 100),
				new Tuple2<Integer,Integer>(2, 90),
				new Tuple2<Integer,Integer>(3, 60),
				new Tuple2<Integer,Integer>(1, 70),
				new Tuple2<Integer,Integer>(2, 80),
				new Tuple2<Integer,Integer>(3, 50));
		JavaPairRDD<Integer, String> students = sc.parallelizePairs(studentList);
		JavaPairRDD<Integer, Integer> scores = sc.parallelizePairs(scoreList);
		JavaPairRDD<Integer, Tuple2<Iterable<String>, Iterable<Integer>>> studentScores = students.cogroup(scores);
		studentScores.foreach(new VoidFunction<Tuple2<Integer,Tuple2<Iterable<String>,Iterable<Integer>>>>() {
 
			@Override
			public void call(
					Tuple2<Integer, Tuple2<Iterable<String>, Iterable<Integer>>> t)
					throws Exception {
				System.out.println(t._1+":"+t._2._1+":"+t._2._2);
				
			}
		}
 
			
		);
		
		sc.close();
	}

迭代计算

image.png

资源复用

image.png

宽、窄依赖

宽依赖:父RDD的分区被子RDD的多个分区使用 例如 groupByKey、reduceByKey、sortByKey等操作会产生宽依赖,会产生shuffle

窄依赖:父RDD的每个分区都只被子RDD的一个分区使用 例如map、filter、union等操作会产生窄依赖

image.png

image.png