一、spark的core:

  • spark中一个core同时只能同时执行一个任务。
  • 计算机的1核1线程(并行一个任务)可以给spark提供1个core,1核2线程(并行两个任务)可以给spark提供2个core。

二、RDD(弹性分布式数据库、RDD中是不存数据的,partition中也不存数据)

  • 一个RDD包含一个或多个partition,一个partition同时只能被一个任务处理。 
  • WordCount中RDD的执行过程

   

spark 一台机器多个executor spark 多线程执行rdd_java

  • RDD五大特性:RDD是由一系列partition组成、算子(函数)是作用于partition上的、RDD之间有依赖关系(当RDD2丢失后,可以根据RDD1通过算子恢复RDD2)、分区器是作用在K、V格式的RDD上、partition对外提供最佳的计算位置,利于数据处理的本地化。

三、问题

  • K、V格式的RDD:RDD中每个元素是一个个的二元组,那么这个RDD就是K、V格式的RDD。
  • sparkContext.textFile():spark没有直接读取HDFS文件的方法,textFile()底层调用的是MR读取HDFS文件的方法,首先会split,每个split默认大小为128M,就是一个block大小,每个split对应一个partition。
  • RDD的弹性(容错):1、RDD partition的个数可多(当数据量大时,可由一个partition拆成多个partition,并且执行)可少(当数据量大时,先由10个partition并行执行过滤,过滤之后每个partition只剩下十条数据,对这10个partition再做下一次操作的时候,需要启动是个任务来执行,启动任务的时候也是需要时间的,这时可以把10个partition合并为1个partition,启动一个任务)。2、RDD之间有依赖关系。
  • RDD的分布式:RDD中的partition分布在多个结点上。

四、WordCount案例

package com.cfl.spark;

import java.util.Arrays;

import org.apache.spark.SparkConf;
import org.apache.spark.api.java.JavaPairRDD;
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.Function2;
import org.apache.spark.api.java.function.PairFunction;
import org.apache.spark.api.java.function.VoidFunction;

import scala.Tuple2;

public class WordCount {

	@SuppressWarnings({ "resource" })
	public static void main(String[] args) {
		
		SparkConf sparkConf = new SparkConf();
		sparkConf.setMaster("local");
		sparkConf.setAppName("测试");
		
		/**
		 * JavaSparkContext 通往集群的唯一通道
		 */
		JavaSparkContext sparkContext = new JavaSparkContext(sparkConf);
		JavaRDD<String> lines = sparkContext.textFile("./test");
		
		/**
		 * flatMap 进一条数据出多条数据,一对多关系
		 */
		JavaRDD<String> words = lines.flatMap(new FlatMapFunction<String, String>() {
			private static final long serialVersionUID = 1L;
			@Override
			public Iterable<String> call(String line) throws Exception {
				return Arrays.asList(line.split(" "));
			}
		});
		
		/**
		 * mapToPair 在java中 如果想让某个RDD转换成K,V格式 使用xxxToPair
		 * K,V格式的RDD:JavaPairRDD<Tuple<String, Integer>>
		 */
		JavaPairRDD<String, Integer> pairWords = words.mapToPair(new PairFunction<String, String, Integer>() {
			private static final long serialVersionUID = 1L;
			public Tuple2<String, Integer> call(String word) throws Exception {
				return new Tuple2<String, Integer>(word, 1);
			}
		});
		
		/**
		 * 1、先将相同的key分组
		 * 2、对每一组的key对应的value去按照逻辑去处理 
		 * Function2:第1个参数(第1条数据的value), 第2个参数(第2条数据的value), 第3个参数(内部方法call的返回值类型),
		 */
		JavaPairRDD<String, Integer> reduce = pairWords.reduceByKey(new Function2<Integer, Integer, Integer>() {
			private static final long serialVersionUID = 1L;
			@Override
			public Integer call(Integer v1, Integer v2) throws Exception {
				return v1+v2;
			}
		});
		
		/**
		 * 排序 先转换K,V -> 按key拍讯 -> 转换回来K,V
		 */
		JavaPairRDD<Integer,String> mapToPair = reduce.mapToPair(new PairFunction<Tuple2<String,Integer>, Integer, String>() {
			private static final long serialVersionUID = 1L;
			@Override
			public Tuple2<Integer, String> call(Tuple2<String, Integer> v) throws Exception {
				return v.swap();
			}
		});
		JavaPairRDD<Integer, String> sortMapToPair = mapToPair.sortByKey(false);
		JavaPairRDD<String, Integer> mapToPair2 = sortMapToPair.mapToPair(new PairFunction<Tuple2<Integer,String>, String, Integer>() {
			private static final long serialVersionUID = 1L;
			@Override
			public Tuple2<String, Integer> call(Tuple2<Integer, String> v) throws Exception {
				return v.swap();
			}
		});
		
		/**
		 * 遍历打印
		 */
		mapToPair2.foreach(new VoidFunction<Tuple2<String,Integer>>() {
			private static final long serialVersionUID = 1L;
			@Override
			public void call(Tuple2<String,Integer> arg0) throws Exception {
				System.out.println(arg0);
			}
		});
		
		// 结束
		sparkContext.stop();
	}
}