— Outline
- 1.原理
- 2.编程
- 2.1 java RDD的输入
- 2.1.1 从输入文件产生RDD
- 2.1.2 程序产生RDD
- 2.2 JavaRDD Transformation
- 2.3 JavaRDD Action
- 2.4 举例
- 2.4.1 word count
- 2.4.2 PageRank
- 3.系统实现
- 4.Spark SQL & Streaming
— 内容
- Spark:面向大数据分析的内存系统。Berkeley AMP Lab研发,可以从HDFS读数据,但是运算中数据放在内存中,不使用Hadoop,而是新实现了分布式的处理。目标是低延迟的分析操作。
- Spark思路
- 内存容量越来越大;把数据放入多台机器的内存以避免HDFS的开销。
1.原理
1.1 基础数据结构RDD(Resilient Distributed Data sets)
- 一个分布式数据集
- 只读(数据集创建后不能修改)
- 通常进行整个数据集的运算
- 优点
- 并发控制被简化
- 可记录lineage(数据集上的运算序列),可重新计算
1.2 两类RDD运算
- Transformation
- Action
- 输入是RDD;输出是某种计算结果(如一个数值或一列数值);RDD–>计算结果。
- RDD可能非常大,但是计算结果总是比较小的。
- 运算过程:读入内存一次,在内存中可以多次处理
2.编程
- scala
- spark支持的主要语言之一
- 一种新的程序设计语言(面向目标的、函数型)
- 在JVM上执行
- 用java做和scala一样的事情
图中红下划线部分是java lambda表达式,可以将其看作是一个匿名的函数,箭头左侧是函数的输入参数,右侧是函数体({return s.contains(“b”)})
2.1 java RDD的输入
- Class JavaRDD< T >:元素类型为T的RDD
- Class JavaPairRDD<K, V>:元素包含一个K和一个V
2.1.1 从输入文件产生RDD
JavaRDD<String> distFile = sc.textFile("data.txt")
- sc是Class JavaSparkContext的一个对象
- 从文本文件读入数据,生成JavaRDD,每个元素是一行文本String
2.1.2 程序产生RDD
Lsit<Integer> data = Arrays.asList(1,2,3,4,5);
JavaRDD<Integer> distData = sc.parallelize(data);
- 用parallelize函数把一个list转换为JavaRDD
2.2 JavaRDD Transformation
B = A.map(x->x+1)
B = A.map(x->new Double(x+1))
words = list.flatMap(s->Arrays.aslist(SPACE.split(s)).iterator());
counts = ones.reduceByKey((x,y)->x+y)
2.3 JavaRDD Action
2.4 举例
2.4.1 word count
public static void main(String[] args) throws Exception{
if(args.length < 1){
System.err.println("Usage: JavaWordCount <file>");
System.exit(1);
}
SparkSession spark = SparkSession
.builder()
.appName("JavaWordCount")
.getOrCreate();
JavaRDD<String> lines = spark.read().textFile(args[0]).javaRDD();
JavaRDD<String> words = lines.flatMap(s->Arrays.aslist(SPACE.split(s)).iterator());
JavaPairRdd<String,Integer> ones = words.mapToPairs(s -> new Tuple2<>(s,1));
JavaPairRdd<String,Integer> counts = ones.reduceByKey((i1,i2) -> i1+i2);
List<Tuple2<String,Integer>> output = counts.collect();
for(Tuple2<?,?> tuple :output){
System.out.println(tuple._1() + ":" + tuple._2());
}
spark.stop();
}
2.4.2 PageRank
public static void main(String[] args) throws Exception{
if(args.length < 1){
System.err.println("Usage: JavaPageRank <file>");
System.exit(1);
}
SparkSession spark = SparkSession
.builder()
.appName("JavaPageRank")
.getOrCreate();
JavaRDD<String> lines = spark.read().textFile(args[0]).javaRDD();
JavaPairRdd<String,Interable<String>> links = lines.mapToPair(s -> {String[] parts = SPACE.split(s);return new Tuple2<>(parts[0],parts[1]);}).distinct().groupByKey().cache();
JavaPairRDD<String,Double> ranks = links.mapValues(rs -> 1.0);
for(int current = 0; current < Integet.parseInt(args[1]); current++){
JavaPairRDD<String, Double> contribs = links.join(ranks).values()
.flatMapToPairs(s -> {
int urlCount = Iterable.size(s._1());
List<Tuple2<String,Double>> results = new ArrayList<>();
for(String n : s._1){
results.add(new Tuple2<>(n, s._2() / urlCount));
}
return results.iterable();
});
ranks = contribs.reduceByKey(a, b->a+b).mapValues(sum -> 0.15 + sum * 0.85);
}
List<Tuple2<String,Double>> output = ranks.collect();
for(Tuple2<?,?> tuple :output){
System.out.println(tuple._1() + ":" + tuple._2());
}
spark.stop();
}
3.系统实现
- 运算过程:读入内存一次,在内存中可以多次处理
- spark运算的运行
- 1.transformation:仅记录,不运算;Lazy execution;
- 2.action:当遇到action时,需要返回结果,才真正执行已经记录的前面的运算
- 3.容错/内存缓冲替换:当内存缓冲的RDD丢失时。可以重新执行记录的运算,重新计算这个RDD
4.Spark SQL & Streaming
- dataFrame
- 1.可以看作是在RDD上定义了Relational Schema
- 2.列可以命名访问
DataSet<Row> df = spark.read().load("file path");
df.printSchema();
df.show();
df.select("name").show(); df.select(col("name"), col("age").plus(1)).show();
df.filter(col("age").gt(21)).show();
df.groupBy("age").count().show();
df.createOrReplaceTempView("people");
DataSet<Row> sqlDF = spark.sql("select * from people");
sqlDF.show();
- Spark Streaming