簡介
看過我前面分享的博客的小夥伴已經知道了基於MR分佈式計算架構的wordcount,現在來進入spark的世界了。
這次我將分享一下基於spark架構的分佈式計算框架,分別實現基於java和scala語言的兩種不同的腳本。
spark-shell初體驗
首先你的虛擬機或者服務器需要先部署spark的僞分佈或者是全分佈模式,這個可以看我以前的blog,然後這次我使用的是僞分佈模式。
安裝好之後我們啓動spark,然後登陸web dashboard查看,然後進入安裝目錄下的bin目錄,打開spark-shell,
命令如下:
./spark-shell --master spark://你的主機名:7077
然後進入shell命令行。
通過spark-shell實現wordcount
這裏我們輸入如下命令:
text.txt是我自己創建的txt文件,大家可以根據自己的路徑
scala> sc.textFile("/text.txt").flatMap( _.split(" ")).map((_,1)).reduceByKey(_+_).collect
這樣就完成了一個最簡單的wordcount。
簡單分析一下:
- textFile讀取文件內容的函數
- flatMap和scala中的一樣,下劃線代表的是每一行,然後用空格做split
- map函數封裝成map格式,這也就是爲什麼裏面要嵌套一層括號,然後給每個map中的value值賦值爲1
- reduceByKey,將相同的key的value相加
- collect表示觸發計算
注:當然也可以用hdfs文件系統上的文件進行操作,但是要確保集羣已經啓動。
scala> sc.textFile("hdfs://集羣IP:9000/1222_1.txt").flatMap(_.split(" ")).map((_,1)).reduceByKey(_+_).saveAsTextFile("hdfs://集羣IP:9000/out/1222_1")
知識點
在這次操作中我覺得有幾點比較重要的點和大家分享一下
對了我再說一下,大家還是需要吧scala的語法夯實一下。
spark的基本單位:RDD:彈性分佈式數據集,他有什麼特點呢:
- 依賴關係 後一個RDD依賴於前一個RDD。
- 算子,這個後面的blog我會分享清楚,現在有一個概念就行。
Transformation 延時計算 flatMap map reduceByKey
- 也就是說,這些函數並不會進行計算,這個scala中的懶值的概念是一樣的。
Action 觸發計算 collect
- 相當於如果不輸入collect就不會觸發計算,那麼即使有錯誤也不會報出。
Idea實現jar包的編寫
首先我們先寫一下提交的命令,這裏我們使用spark-submit工具,因爲spark-shell其實真正應用的時候是非常少的,一般都是使用和spark-shell同目錄級的spark-submit工具。
下面我將分享一下scala和java的jar包編寫,然後下面是jar包的提交運行命令。
spark-submit --master spark://spark81:7077 --class 類reference jar包目錄 args[0] args[1]
上面的args[0] args[1]一般是輸入輸出路徑。
下面我寫的local模式,如果大家想用spark-submit提交到集羣運行,那麼就將setMater()去掉。
java:
package wordcount;
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 scala.Tuple2;
import java.util.Arrays;
import java.util.Iterator;
import java.util.List;
import java.util.regex.Pattern;
/**
* @Author: Braylon
* @Date: 2020/2/9 11:52
* @Version: 1.0
*/
public class wordcount {
private static final Pattern SPACE = Pattern.compile(" ");
public static void main(String[] args) {
SparkConf conf = new SparkConf().setAppName("JAVA_wordcount").setMaster("local");
JavaSparkContext context = new JavaSparkContext(conf);
JavaRDD<String> lines = context.textFile("D:\\idea\\projects\\scalaDemo\\resources\\text.txt");
JavaRDD<String> terms = lines.flatMap(new FlatMapFunction<String, String>() {
public Iterator<String> call(String s) throws Exception {
return Arrays.asList(SPACE.split(s)).iterator();
}
});
JavaPairRDD<String, Integer> ones = terms
.mapToPair(new PairFunction<String, String, Integer>() {
public Tuple2<String, Integer> call(String s) throws Exception {
return new Tuple2<String, Integer>(s, 1);
}
});
JavaPairRDD<String, Integer> counts = ones
.reduceByKey(new Function2<Integer, Integer, Integer>() {
public Integer call(Integer integer, Integer integer2) throws Exception {
return integer + integer2;
}
});
List<Tuple2<String, Integer>> result = counts.collect();
for (Tuple2 item : result) {
System.out.println(item._1() + "-->" + item._2());
}
context.stop();
}
}
scala:
package myDemo06
import org.apache.spark.{SparkConf, SparkContext}
/**
* @Author: Braylon
* @Date: 2019/12/24 13:08
* @Version: 1.0
*/
object wordcount {
def main(arg: Array[String]): Unit = {
/*
* 如果Master是local,表示在本地運行,可以在IDE中運行
* 若需要提交到集羣中,就不需要設置Master
* */
val conf = new SparkConf().setAppName("wordcount").setMaster("local")
//創建SparkContext對象
val sc = new SparkContext(conf)
val result = sc.textFile("D:\\idea\\projects\\scalaDemo\\resources\\text.txt")
.flatMap(_.split(" "))
.map((_,1))
.reduceByKey(_+_)
.collect
result.foreach(println)
sc.stop()
}
}
我也在學習的路上,歡迎指正
大家共勉~!