#大数据#
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。
适用场景
-
Spark是基于内存的迭代计算框架,适用于需要多次操作特定数据集的应用场合。需要反复操作的次数越多,所需读取的数据量越大,受益越大,数据量小但是计算密集度较大的场合,受益就相对较小。
-
由于RDD的特性,Spark不适用那种异步细粒度更新状态的应用,例如web服务的存储或者是增量的web爬虫和索引。就是对于那种增量修改的应用模型不适合。
-
数据量不是特别大,但是要求实时统计分析需求。
系统架构
RDD (Resilient Distributed Dataset) 弹性分布式数据集
- 弹性-因为Spark RDD的数据大部分情况下是在内存中的,这也是Spark运行速度比MapReduce/ Hive快很多的原因,但在内存资源不足时,它会自动根据资源情况弹性地利用磁盘来保存一小部分 数据。
- 分布式-在Spark中,对数据的操作无外乎是创建RDD,转换RDD,以及调用RDD的action操作进行 计算。Spark 会自动将RDD中的数据分发到集群的不同节点,并将操作并行化执行。
RDD运行过程
创建/转换RDD → 构建DAG → 划分Stage → 分发到Executor执行。
Stage的划分
根据RDD分区的依赖关系划分Stage:
- 在DAG中进行反向解析,遇到宽依赖就断开,遇到窄依赖就把当前的RDD加入到当前Stage中;
- 将窄依赖尽量划分在同一个Stage中,可以实现流水线计算;
RDD操作过程
Why we use Spark?
Spark VS MR
丰富的计算因子
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();
}
迭代计算
资源复用
宽、窄依赖
宽依赖:父RDD的分区被子RDD的多个分区使用 例如 groupByKey、reduceByKey、sortByKey等操作会产生宽依赖,会产生shuffle
窄依赖:父RDD的每个分区都只被子RDD的一个分区使用 例如map、filter、union等操作会产生窄依赖