一、Spark-Submit提交參數
1.1、補充算子
transformations:
(1)mapPartitionWithIndex:類似於mapPartitions,除此之外還會攜帶分區的索引值。
(2)repartition:增加或減少分區。會產生shuffle。(多個分區分到一個分區不會產生shuffle)
(3)coalesce:coalesce常用來減少分區,第二個參數是減少分區的過程中是否產生shuffle。
true爲產生shuffle,false不產生shuffle。默認是false。
如果coalesce設置的分區數比原來的RDD的分區數還多的話,第二個參數設置爲false不會起作用,如果設置成true,效果和repartition一樣。即repartition(numPartitions) = coalesce(numPartitions,true)
(4)groupByKey:作用在K,V格式的RDD上。根據Key進行分組。作用在(K,V),返回(K,Iterable <V>)。
(5)zip:將兩個RDD中的元素(KV格式/非KV格式)變成一個KV格式的RDD,兩個RDD的每個分區元素個數必須相同。
(6)zipWithIndex:該函數將RDD中的元素和這個元素在RDD中的索引號(從0開始)組合成(K,V)對。
Action:
(1)countByKey:作用到K,V格式的RDD上,根據Key計數相同Key的數據集元素。
(2)countByValue:根據數據集每個元素相同的內容來計數。返回相同內容的元素對應的條數。
(3)reduce:根據聚合邏輯聚合數據集中的每個元素。
1.2、補充 PV&UV概念瞭解
(1)PV
什麼是PV:是網站分析的一個術語,用以衡量網站用戶訪問的網頁的數量。對於廣告主,PV值可預期它可以帶來多少廣告收入。一般來說,PV與來訪者的數量成正比,但是PV並不直接決定頁面的真實來訪者數量,如同一個來訪者通過不斷的刷新頁面,也可以製造出非常高的PV。
什麼是PV值:
所有訪問者在24小時(0點到24點)內看了某個網站多少個頁面或某個網頁多少次。PV是指頁面刷新的次數,每一次頁面刷新,就算做一次PV流量。
度量方法:
度量方法就是從瀏覽器發出一個對網絡服務器的請求(Request),網絡服務器接到這個請求後,會將該請求對應的一個網頁(Page)發送給瀏覽器,從而產生了一個PV。那麼在這裏只要是這個請求發送給了瀏覽器,無論這個頁面是否完全打開(下載完成),那麼都是應當計爲1個PV。
(2)什麼是UV值
即獨立訪客數,指訪問某個站點或點擊某個網頁的不同IP地址的人數。在同一天內,UV只記錄第一次進入網站的具有獨立IP的訪問者,在同一天內再次訪問該網站則不計數。UV提供了一定時間內不同觀衆數量的統計指標,而沒有反應出網站的全面活動。
1.3、Spark-Submit提交參數
(1)Options:
- --master: MASTER_URL, 可以是spark://host:port, mesos://host:port, yarn, yarn-cluster,yarn-client, local
- --deploy-mode:DEPLOY_MODE, Driver程序運行的地方,client或者cluster,默認是client。
- --class:CLASS_NAME, 主類名稱,含包名
- --jars:逗號分隔的本地JARS, Driver和executor依賴的第三方jar包
- --files:用逗號隔開的文件列表,會放置在每個executor工作目錄中
- --conf:spark的配置屬性
- --driver-memory:Driver程序使用內存大小(例如:1000M,5G),默認1024M
- --executor-memory:每個executor內存大小(如:1000M,2G),默認1G
(2)Spark standalone with cluster deploy mode only
- --driver-cores:Driver程序的使用core個數(默認爲1),僅限於Spark standalone模式
(3)Spark standalone or Mesos with cluster deploy mode only
- --supervise:失敗後是否重啓Driver,僅限於Spark alone或者Mesos模式
(4)Spark standalone and Mesos only
- --total-executor-cores:executor使用的總核數,僅限於SparkStandalone、Spark on Mesos模式
(5)Spark standalone and YARN only
- --executor-cores:每個executor使用的core數,Spark on Yarn默認爲1,standalone默認爲worker上所有可用的core。
(6)YARN-only
- --driver-cores:driver使用的core,僅在cluster模式下,默認爲1。
- --queue :QUEUE_NAME 指定資源隊列的名稱,默認:default
- --num-executors:一共啓動的executor數量,默認是2個。
二、編碼
2.1、二次排序
SparkConf sparkConf = new SparkConf()
.setMaster("local")
.setAppName("SecondarySortTest");
final JavaSparkContext sc = new JavaSparkContext(sparkConf);
JavaRDD<String> secondRDD = sc.textFile("secondSort.txt");
JavaPairRDD<SecondSortKey, String> pairSecondRDD = secondRDD.mapToPair(new PairFunction<String, SecondSortKey, String>() {
/**
*
*/
private static final long serialVersionUID = 1L;
@Override
public Tuple2<SecondSortKey, String> call(String line) throws Exception {
String[] splited = line.split(" ");
int first = Integer.valueOf(splited[0]);
int second = Integer.valueOf(splited[1]);
SecondSortKey secondSortKey = new SecondSortKey(first,second);
return new Tuple2<SecondSortKey, String>(secondSortKey,line);
}
});
pairSecondRDD.sortByKey(false).foreach(new
VoidFunction<Tuple2<SecondSortKey,String>>() {
/**
*
*/
private static final long serialVersionUID = 1L;
@Override
public void call(Tuple2<SecondSortKey, String> tuple) throws Exception {
System.out.println(tuple._2);
}
});
public class SecondSortKey implements Serializable,Comparable<SecondSortKey>{
/**
*
*/
private static final long serialVersionUID = 1L;
private int first;
private int second;
public int getFirst() {
return first;
}
public void setFirst(int first) {
this.first = first;
}
public int getSecond() {
return second;
}
public void setSecond(int second) {
this.second = second;
}
public SecondSortKey(int first, int second) {
super();
this.first = first;
this.second = second;
}
@Override
public int compareTo(SecondSortKey o1) {
if(getFirst() - o1.getFirst() ==0 ){
return getSecond() - o1.getSecond();
}else{
return getFirst() - o1.getFirst();
}
}
}
2.2、分組取topN和topN
SparkConf conf = new SparkConf()
.setMaster("local")
.setAppName("TopOps");
JavaSparkContext sc = new JavaSparkContext(conf);
JavaRDD<String> linesRDD = sc.textFile("scores.txt");
JavaPairRDD<String, Integer> pairRDD = linesRDD.mapToPair(new PairFunction<String, String, Integer>() {
/**
*
*/
private static final long serialVersionUID = 1L;
@Override
public Tuple2<String, Integer> call(String str) throws Exception {
String[] splited = str.split("\t");
String clazzName = splited[0];
Integer score = Integer.valueOf(splited[1]);
return new Tuple2<String, Integer> (clazzName,score);
}
});
pairRDD.groupByKey().foreach(new
VoidFunction<Tuple2<String,Iterable<Integer>>>() {
/**
*
*/
private static final long serialVersionUID = 1L;
@Override
public void call(Tuple2<String, Iterable<Integer>> tuple) throws Exception {
String clazzName = tuple._1;
Iterator<Integer> iterator = tuple._2.iterator();
Integer[] top3 = new Integer[3];
while (iterator.hasNext()) {
Integer score = iterator.next();
for (int i = 0; i < top3.length; i++) {
if(top3[i] == null){
top3[i] = score;
break;
}else if(score > top3[i]){
for (int j = 2; j > i; j--) {
top3[j] = top3[j-1];
}
top3[i] = score;
break;
}
}
}
System.out.println("class Name:"+clazzName);
for(Integer sscore : top3){
System.out.println(sscore);
}
}
});
三、SparkShell的使用
(1)概念
SparkShell是Spark自帶的一個快速原型開發工具,也可以說是Spark的scala REPL(Read-Eval-Print-Loop),即交互式shell。支持使用scala語言來進行Spark的交互式編程。
(2)使用
啓動Standalone集羣,./start-all.sh
在客戶端上啓動spark-shell:
./spark-shell --master spark://node1:7077
啓動hdfs,創建目錄spark/test,上傳文件wc.txt
啓動hdfs集羣:
start-all.sh
創建目錄:
hdfs dfs -mkdir -p /spark/test
上傳wc.txt
hdfs dfs -put /root/test/wc.txt /spark/test/
wc附件:
運行wordcount
sc.textFile("hdfs://node1:9000/spark/test/wc.txt")
.flatMap(_.split(" ")).map((_,1)).reduceByKey(_+_).foreach(println)