spark學習筆記
spark介紹
MapReduce存在的缺陷:
Spark的模組組成
spark的使用模式
Spark最核心的資料抽象
注意:
scala>rdd.collect
收集rdd中的資料組成Array返回,此方法將會把分散式儲存的rdd中的資料集中到一臺機器中組建Array。
在生產環境下一定要慎用這個方法,容易記憶體溢位
RDD操作
每一個懶操作都會只生成一個rdd物件,但是資料沒有載入進來,只有執行了一個action操作,資料才會載入進來
Transformations
map(func)
案例展示:
map 將函式應用到rdd的每個元素中
val rdd = sc.makeRDD(List(1,3,5,7,9))
rdd.map(*10)
flatMap(func)
案例展示:
flatMap 扁平map處理
val rdd = sc.makeRDD(List(“hello world”,“hello count”,“world spark”),2)
rdd.map(.split{" "})//Array(Array(hello, world), Array(hello, count), Array(world, spark))
rdd.flatMap(.split{" "})//Array[String] = Array(hello, world, hello, count, world, spark)
//Array[String] = Array(hello, world, hello, count, world, spark)
注:map和flatMap有何不同?
map: 對RDD每個元素轉換
flatMap: 對RDD每個元素轉換, 然後再扁平化(即去除集合)
所以,一般我們在讀取資料來源後,第一步執行的操作是flatMap
filter(func)
案例展示:
filter 用來從rdd中過濾掉不符合條件的資料
val rdd = sc.makeRDD(List(1,3,5,7,9));
rdd.filter(<5);
union(otherDataset)
案例展示:
union 並集 – 也可以用++實現
val rdd1 = sc.makeRDD(List(1,3,5));
val rdd2 = sc.makeRDD(List(2,4,6,8));
val rdd = rdd1.union(rdd2);
val rdd = rdd1 ++ rdd2;
intersection(otherDataset)
案例展示:
intersection 交集
val rdd1 = sc.makeRDD(List(1,3,5,7));
val rdd2 = sc.makeRDD(List(5,7,9,11));
val rdd = rdd1.intersection(rdd2);
subtract
案例展示:
subtract 差集
val rdd1 = sc.makeRDD(List(1,3,5,7,9));
val rdd2 = sc.makeRDD(List(5,7,9,11,13));
val rdd = rdd1.subtract(rdd2);
distinct([numTasks]))
Return a new dataset that contains the distinct elements of the source dataset.
沒有引數,將RDD裡的元素進行去重操作
案例展示:
val rdd = sc.makeRDD(List(1,3,5,7,9,3,7,10,23,7));
rdd.distinct
groupByKey([numTasks])
案例展示:
scala>val rdd = sc.parallelize(List((“cat”,2), (“dog”,5),(“cat”,4),(“dog”,3),(“cat”,6),(“dog”,3),(“cat”,9),(“dog”,1)),2);
scala>rdd.groupByKey()
注:groupByKey對於資料格式是有要求的,即操作的元素必須是一個二元tuple,
tuple.1 是key, tuple.2是value
比如下面這種資料格式:
sc.parallelize(List(“dog”, “tiger”, “lion”, “cat”, “spider”, “eagle”), 2)就不符合要求
以及這種:
sc.parallelize(List((“cat”,2,1), (“dog”,5,1),(“cat”,4,1),(“dog”,3,2),(“cat”,6,2),(“dog”,3,4),(“cat”,9,4),(“dog”,1,4)),2);
reduceByKey(func, [numTasks])
案例展示:
scala>var rdd = sc.makeRDD( List( (“hello”,1),(“spark”,1),(“hello”,1),(“world”,1) ) )
rdd.reduceByKey(+);
注:reduceByKey操作的資料格式必須是一個二元tuple
sortByKey([ascending], [numTasks])
案例展示:
val d2 = sc.parallelize(Array((“cc”,32),(“bb”,32),(“cc”,22),(“aa”,18),(“bb”,6),(“dd”,16),(“ee”,104),(“cc”,1),(“ff”,13),(“gg”,68),(“bb”,44)))
d2.sortByKey(true).collect
join(otherDataset, [numTasks])
案例展示:
val rdd1 = sc.makeRDD(List((“cat”,1),(“dog”,2)))
val rdd2 = sc.makeRDD(List((“cat”,3),(“dog”,4),(“tiger”,9)))
rdd1.join(rdd2);
cartesian(otherDataset)
案例展示:
cartesian 笛卡爾積
val rdd1 = sc.makeRDD(List(1,2,3))
val rdd2 = sc.makeRDD(List(“a”,“b”))
rdd1.cartesian(rdd2);
coalesce(numPartitions)
coalesce(n,true/false) 擴大或縮小分割槽
案例展示:
val rdd = sc.makeRDD(List(1,2,3,4,5),2)
rdd.coalesce(3,true);//如果是擴大分割槽 需要傳入一個true 表示要重新shuffle
rdd.coalesce(2);//如果是縮小分割槽 預設就是false 不需要明確的傳入
Actions
reduce(func)
使用該函式(接受兩個引數並返回一個)聚合資料集的元素。函式應該是可交換的和結合的,這樣就可以正確地平行計算。
collect()
返回RDD所有元素,將rdd分散式儲存在叢集中不同分割槽的資料 獲取到一起組成一個陣列返回。要注意 這個方法將會把所有資料收集到一個機器內,容易造成記憶體的溢位 在生產環境下千萬慎用
count()
統計RDD裡元素個數
案例展示:
val rdd = sc.makeRDD(List(1,2,3,4,5),2)
rdd.count
first()
取出第一個元素
takeOrdered(n, [ordering])
takeOrdered(n) 先將rdd中的資料進行升序排序 然後取前n個
val rdd = sc.makeRDD(List(52,31,22,43,14,35))
rdd.takeOrdered(3)
top(n)
top(n) 先將rdd中的資料進行降序排序 然後取前n個
val rdd = sc.makeRDD(List(52,31,22,43,14,35))
rdd.top(3)
saveAsTextFile(path)
saveAsTextFile 按照文字方式儲存分割槽資料
val rdd = sc.makeRDD(List(1,2,3,4,5),2);
rdd.saveAsTextFile("/root/work/aaa")
countByKey()
僅在型別(K,V)的RDD上可用。返回(K,Int)對的hashmap及其每個鍵的計數。
foreach(func)
遍歷rdd
單機狀態下使用eclipse操作spark
所需要的jar包地址:
https://gitee.com/light__pro/bigdata/tree/master/jars
package cn.tedu.wordcount
/**
* 統計單詞個數案例
*/
import org.apache.spark.SparkConf
import org.apache.spark.SparkContext
object Driver {
def main(args: Array[String]): Unit = {
//建立Spark的環境引數物件,必須設定兩個引數
//setMaster:指定執行模。local表示本地單機模式
//setAppName:指定應用程式id,使用者自定義
val conf=new SparkConf().setMaster("local").setAppName("wordcount")
//建立Spark的上下文物件,通過此物件操作Spark
val sc=new SparkContext(conf)
val data=sc.textFile("hdfs://hadoop01:9000/01.txt",2)
val result=data.flatMap { x => x.split(" ") }
.map { x => (x,1) }
.reduceByKey{_+_}
result.foreach{println}
result.saveAsTextFile("hdfs://hadoop01:9000/wordcount")
}
package cn.tedu.maxmin
import org.apache.spark.SparkContext
import org.apache.spark.SparkConf
/**
* 處理MaxMin.txt,返回女性最小身高的前兩條資料
*
* 過濾 排序 取值
*
* */
object Driver02 {
def main(args: Array[String]): Unit = {
val conf=new SparkConf().setMaster("local").setAppName("wordcount")
//建立Spark的上下文物件,通過此物件操作Spark
val sc=new SparkContext(conf)
val data=sc.textFile("d://data/MaxMin.txt",2)
val ss=data.filter { x => x.split(" ") (1).equals("F")}.sortBy(x=>x.split(" ") (2).toInt).take(2)
ss.foreach { println }
}}
package cn.tedu.topk
import org.apache.spark.SparkConf
import org.apache.spark.SparkContext
/**
* 處理top.txt,返回單詞頻次最高的前3項單詞資料
*hello world bye world
hello hadoop bye hadoop
hello world java web
hadoop scala java hive
* */
object Driver {
def main(args: Array[String]): Unit = {
val conf=new SparkConf().setMaster("local").setAppName("wordcount")
//建立Spark的上下文物件,通過此物件操作Spark
val sc=new SparkContext(conf)
val data=sc.textFile("d://data/topk.txt",2)
val ss= data.flatMap { x => x.split(" ") }.map{x=>(x,1)}.reduceByKey{_+_}
val aa=ss.take(3)
aa.foreach(println)
}
}
**課後作業:**找出一段資料的中位數和方差
package cn.tedu.homework
import org.apache.spark.SparkConf
import org.apache.spark.SparkContext
/**
* 1.處理median.txt,找出這一組資料的中位數。 正確結果是10
*
* 比如一組資料:
* 3 1 7 5 9
*
* 1 3 5 7 9 中位數是5 中位數的位置:(n+1)/2=3
* 1 3 5 7 9 11 中位數是(5+7)/2
*
* 課後作業,只需要考慮元素個數是奇數個情況
*
* 2.處理median.txt,計算出這組資料的方差。
*
* 比如一組資料:
* 1 2 3 4 5 avg=3
* [(1-3)^2+(2-3)^2+(3-3)^2 ...]/5
*/
object Driver {
def main(args: Array[String]): Unit = {
val conf=new SparkConf().setMaster("local").setAppName("median")
val sc=new SparkContext(conf)
val data=sc.textFile("d://data/median.txt")
//RDD[line:String]->flatMap:RDD[num:Int]->sortBy 升序排序
val r1=data.flatMap { line => line.split(" ") }
.map { num => num.toInt }
.sortBy{num => num}
//課後作業1:
//獲取中位數的位置
val pos=((r1.count()+1)/2).toInt
//方式1:RDD無法直接通過下標進行操作,所以如果要通過下標操作,需要先轉變為普通集合型別Array再操作
//val result=r1.collect()(pos-1)
//方式2:通過take方式來實現
val result=r1.take(pos).last
//課後作業2:
val avg=r1.sum/r1.count
val variance=r1.map { num => (num-avg)*(num-avg) }.sum/r1.count
}
}
史上最難spark題
輸出一組檔案的倒排索引
package cn.tedu.invert
import org.apache.spark.SparkConf
import org.apache.spark.SparkContext
/**
* 處理inverted目錄的所有檔案,通過spark最後要輸出一個簡易的倒排索引表,比如:
* (hello,doc1,doc2)
* (hadoop,doc1,doc3)
* ......
每一個檔案資料大概:
hello hive
hello hbase
hello spark
*/
object Driver {
def main(args: Array[String]): Unit = {
val conf =new SparkConf().setMaster("local").setAppName("invert")
val sc=new SparkContext(conf)
//將指定目錄下的所有檔案讀取到一個RDD中,每有一個檔案會形成一個二元元組。
//返回的RDD[(filePath,fileText)]
val data=sc.wholeTextFiles("d://data/inverted/*")
//處理思路:
//1.通過filePath獲取文件名
//2.通過fileText獲取單詞。先\r\n 切出行,再按空格切單詞
//3.按單詞分組,輸出要求的倒排表
//第一步:RDD[(filePath,fileText)]->map:RDD[(fileName,fileText)]
val r1=data.map{case(filePath,fileText)=>
val fileName=filePath.split("/").last.dropRight(4)
(fileName,fileText)
}
//第二步:RDD[(fileName,fileText)]->flatMap:RDD[(word,fileName)]
val r2=r1.flatMap{case(fileName,fileText)=>
fileText.split("\r\n").flatMap { line => line.split(" ") }
.map { word =>(word,fileName)}
}
//第三步:按單詞分組,輸出倒排表。r2現在是一個陣列,陣列的元素是一個二元元組,二元元組第一個是單詞陣列,第//二個是對應的檔名稱
val r3=r2.groupByKey.map { case(word,it) =>(word,it.toArray.distinct.mkString(",")) }
r3.foreach{println}
}
}
Spark的DAG概念
RDD的依賴關係
藉助這些依賴關係,DAG可以認為這些RDD之間形成了Lineage(血統,血緣關係)。藉助Lineage,能保證一個RDD被計算前,它所依賴的parent RDD都已經完成了計算;同時也實現了RDD的容錯性,即如果一個RDD的部分或者全部的計算結果丟失了,那麼就需要重新計算這部分丟失的資料
子RDD的Partition是parent RDD的所有Partition Shuffle的結果。
stage的劃分
原始的RDD經過一系列轉換後(一個DAG),會在最後一個RDD上觸發一個動作,這個動作會生成一個Job。
所以可以這樣理解:一個DAG對應一個Spark的Job。
spark基礎核心概念總結
對應關係:
一個DAG對應一個Spark的Job。
一個Action對應一個Job任務。
一個分割槽對應一個task。
一個Stage是一組Task的集合
一個應用程式對應一個sc,一個應用程式至少包含一個job
spark圖形化工具的使用
Spark叢集搭建
啟動叢集:
進入Spark的bin目錄下,執行:
sh spark-shell --master spark://hadoop01:7077
提交應用程式到Spark叢集執行
程式碼:
package cn.tedu.wordcount
import org.apache.spark.SparkConf
import org.apache.spark.SparkContext
object Driver {
def main(args: Array[String]): Unit = {
//spark://hadoop01:7077:設定執行模式Spark叢集模式,這種模式下不能直接啟動執行,
//需要打成jar包上傳伺服器執行
//eclipse打jar包的步驟:工程上右鍵->export->java->jar file->只勾選程式碼並指定路徑->finish即可
val conf=new SparkConf().setMaster("spark://hadoop01:7077")
.setAppName("wordcount")
val sc=new SparkContext(conf)
//如果是Spark叢集模式執行,建議分割槽數量一般都是大於伺服器數量,可以確保每臺伺服器可以獲取分割槽資料進行處理
val data=sc.textFile("hdfs://hadoop01:9000/01.txt", 3)
val wordcount=data.flatMap {_.split(" ")}.map{(_,1)}.reduceByKey{_+_}
wordcount.coalesce(1).saveAsTextFile("hdfs://hadoop01:9000/wordcount-result")
}
}
Spark叢集架構說明
SparkContext底層的任務排程流程
SparkContext底層有三個排程模組:
1.DAG排程模組
2.Task排程模組
3.Backend排程模組
Spark叢集架構細節補充
擴充套件內容 VMS演算法
關於相似度:使用協方差來描述
可以通過協方差的正負來判斷是正相關、負相關、還是不相關
相關係數:
向量間的夾角餘弦:
zz
相關文章
- spark學習筆記--Spark SQLSpark筆記SQL
- spark學習筆記-- Spark StreamingSpark筆記
- Spark學習筆記(三)-Spark StreamingSpark筆記
- spark學習筆記--RDDSpark筆記
- spark學習筆記--叢集執行SparkSpark筆記
- spark學習筆記--Spark調優與除錯Spark筆記除錯
- spark學習筆記--RDD鍵對操作Spark筆記
- spark學習筆記--進階程式設計Spark筆記程式設計
- spark學習筆記--資料讀取與儲存Spark筆記
- spark筆記Spark筆記
- Spark學習——記憶體管理Spark記憶體
- numpy的學習筆記\pandas學習筆記筆記
- 學習筆記筆記
- Spark簡明筆記Spark筆記
- spark 學習Spark
- 【學習筆記】數學筆記
- 機器學習學習筆記機器學習筆記
- 《JAVA學習指南》學習筆記Java筆記
- 學習筆記-粉筆980筆記
- fastadmin學習筆記AST筆記
- JAVA學習筆記Java筆記
- FFT學習筆記FFT筆記
- HTML學習筆記HTML筆記
- wireshark學習筆記筆記
- LCA學習筆記筆記
- Tarjan 學習筆記筆記
- TensorFlow 學習筆記筆記
- PyTorch 學習筆記PyTorch筆記
- 字串學習筆記字串筆記
- Go 學習筆記Go筆記
- Bash 學習筆記筆記
- argparse學習筆記筆記
- Rust 學習筆記Rust筆記
- Python學習筆記Python筆記
- SpringBoot學習筆記Spring Boot筆記
- 吉他學習筆記筆記
- PHP 學習筆記PHP筆記
- Docker學習筆記Docker筆記