1 spark簡介
Spark是基於內存計算的大數據分佈式計算框架,提高了大數據環境下數據處理的實時性。
分佈式計算
內存計算
容錯
多計算範式
2 安裝部署 spark on yarn
master 192.168.100.200
slave1: 192.168.100.201
slave2:192.168.100.202
hadoop環境
2.1 安裝scala環境
tar -zxvf scala-2.10.6.tgz
vi /etc/profile
SCALA_HOME=/usr/local/scala-2.10.6
PATH=$SCALA_HOME/bin:$PATH
export SCAlA_HOME
export PATH
source /etc/profile
在命令行輸入:scala測試安裝成功
2.2 安裝spark
tar -zxvf spark-2.1.0-bin-hadoop2.7.tgz
cd spark-2.1.0-bin-hadoop2.7/conf/
cp spark-env.sh.template spark-env.sh
vi spark-env.sh
export SPARK_HOME=/usr/local/spark-2.1.0-bin-hadoop2.7/
export SCALA_HOME=/usr/local/scala-2.10.6/
export JAVA_HOME=/usr/local/jdk1.7.0_79/
export HADOOP_HOME=/usr/local/hadoop-2.7.1/
export PATH=$PATH:$JAVA_HOME/bin:$HADOOP_HOME/bin:$HADOOP_HOME/sbin:$SCALA_HOME/bin
export HADOOP_CONF_DIR=$HADOOP_HOME/etc/hadoop
export YARN_CONF_DIR=$YARN_HOME/etc/hadoop
export SPARK_MASTER_IP=master
SPARK_LOCAL_DIRS=/usr/local/spark-2.1.0-bin-hadoop2.7/spadata
SPARK_DRIVER_MEMORY=1G
export SPARK_LIBARY_PATH=.:$JAVA_HOME/lib:$JAVA_HOME/jre/lib:$HADOOP_HOME/lib/native
root@master spark-2.1.0-bin-hadoop2.7]# mkdir spadata
cp slaves.template slaves
vi slaves
slave1
slave2
scp -r spark-2.1.0-bin-hadoop2.7 slave1:/usr/local/
scp -r spark-2.1.0-bin-hadoop2.7 slave2:/usr/local/
2.3 啓動
sbin/start-all.sh
2.4 web頁面
http://192.168.100.200:8080/
2.5 運行
./bin/spark-submit --class org.apache.spark.examples.SparkPi --master yarn --deploy-mode cluster --driver-memory 1G --executor-memory 1G --executor-cores 1 examples/jars/spark-examples_2.11-2.1.0.jar 40
2.6 hadoop頁面
http://192.168.100.200:8088 可以在hadoop管理界面看到spark運行任務
3 spark組件簡介
3.1 spark架構組件
Master負責集羣整體資源管理和調度
Worker負責單個節點的資源管理,啓動Excutor、Driver
Driver 應用邏輯執行的起點,創建SparkContext
Executor 對數據進行並行處理
3.2 spark應用
SparkContext整個應用的上下文,控制應用的生命週期
RDD,Spark基本計算單元,一組RDD形成執行的有向無環圖RDD Graph
DAG Scheduler 根據Job創建基於Stage的DAG,並提交Stage給TaskScheduler
TaskScheduler 將Task分發給Executor執行
SparkEnv 線程級別的上下文,存儲運行時的重要組件的引用
4 執行機制
Client提交應用,Master找到一個Worker啓動Driver
Driver向Master申請資源,之後將應用轉換爲RDD Graph
再由DAG Scheduler 將RDD Graph 轉換爲Stage的有向無環圖
提交給TaskScheduler,由TaskScheduler提交任務給Executor執行
任務 執行的過程中SparkEnv提供支持
5 RDD理解
5.1 組成部分
一系列的分區,用來管理數據
計算分區數據的函數
依賴關係,lineage(血緣關係)
spark 入門案例
[root@master bin]# ./spark-shell
該環境下已經存在一個SparkContext,即sc
scala> var list = sc.makeRDD(List(1,3,5,7,9)) //將普通集合轉換成RDD集合
scala> var list2 = list.map { x => x + 1} //map中的元素+1,這一步沒有立即執行 ,返回的一個新的RDD
scala> list2.collect //觸發計算
RDD數據分區管理
分區1 分區2 partition
1,3 5,7,9
當collect方法時:
1) 根據分區劃分任務Task(RDD集合、RDD集合執行的函數)
task1 (1,3 、 list.map { x => x + 1})
task2 (5,7,9 、 list.map { x => x + 1})
2) 把task交給Master
3) Master把任務進行序列化處理,發送給Worker
4) Worker把任務反序列成對象
task1 (1,3 、 list.map { x => x + 1}) => 2,4 (worker1)
task2 (5,7,9 、 list.map { x => x + 1}) => 6,8,10 (worker2)
5) 當執行的是collect方法時,會把worker的運算結果返回給driver,在driver合併結果
scala> var list = sc.makeRDD(List(1,3,5,7,9),2) //將普通集合轉換成RDD集合,分區數爲2
wordcount案例
[root@master bin]# cat wordcount
hello spark i am wang yong long
i think you are very smart
spark
scala> var list = sc.textFile("file:///usr/local/spark-2.1.0-bin-hadoop2.7/bin/wordcount",2) //根據文本文件創建RDD集合
var list2 = list.flatMap{x => x.split(" ")} //根據空格切分數據
scala> list2.take(2)
res10: Array[String] = Array(hello, spark)
scala> var list3 = list2.map { x => (x,1)}
scala> list3.take(2)
res12: Array[(String, Int)] = Array((hello,1), (spark,1))
scala> val list4 = list3.reduceByKey{(x,y)=> x+y}
scala> list4.collect
res13: Array[(String, Int)] = Array((are,1), (long,1), (am,1), (think,1), (very,1), (hello,1), (spark,2), (you,1), (yong,1), (i,2), (smart,1), (wang,1))
transformations(轉換方法)
map,flatMap,reduceByKey,filter都屬於懶惰方法,僅僅返回新的RDD集合,並沒有立刻執行計算
Actions(行動方法)
collect,first,take觸發計算
當一個action方法觸發時,就會觸發一次job,一個job中包含多個Task
查看每個worker輸出日記,在對應的worker上$SPARK_HOME/work/目錄下
2 spark部署方式
Driver:驅動(計算的發起者)
Master: 任務的分配和分發
Worker:執行計算任務
./spark-shell --master=spark://master:7077
7077端口負責監聽driver,worker對master的連接
8088端口提供web界面
3 spark與hdfs整合
[root@slave2 hadoop-2.7.1]# bin/hadoop fs -ls /
[root@slave2 hadoop-2.7.1]# bin/hadoop fs -put /usr/local/wordcount /user
scala> val list = sc.textFile("hdfs://master:9000/user/wordcount")
scala> list.first
4 深入理解RDD
4.1 RDD五個組成部分
一系列的分區,按分區來管理數據
計算分區數據的函數
依賴關係 lineage(血緣關係),父子RDD的依賴關係
分區器
HashPartitioner 根據數據的哈希值分區
RangePartitioner 將所有數據進行採樣,根據數據大小範圍分區
優選位置
跨機器節點讀取數據時,最近最優的節點位置
4.2 緩存
傳統MapReduce計算的中間結果必須落地,增大了磁盤的IO操作
Spark可以將RDD,包括內部數據,緩存在內存中,分佈式緩存
緩存是spark比hadoop快的主要原因之一
spark的內存佔用劃分爲兩個部分:緩存、計算
4.3 累加器
scala> var count = sc.accumulator(0) //分佈式環境下,真正的全局變量
scala> var rdd = sc.makeRDD(List(1,2,3,4,5))
scala> rdd.foreach(x => count+=x)
scala> println(count.value)
4.4 廣播變量
跟緩存相關,將rdd廣播到每一個節點上(driver端廣播到每一個worker節點緩存中)
scala> var rdd = sc.makeRDD(List(1,2,3,4,5))
scala> sc.broadcast(rdd)
5 shuffle過程
5.1 窄依賴、寬依賴
寬依賴:分區的數據如果分別來自於父RDD的某幾個分區
窄依賴:分區的數據如果完全來自父RDD的一個或者幾個分區
5.2 shuffle
分區的數據需要重新分組,這個過程爲shuffle
窄依賴不需要shuffle,寬依賴需要shuffle
5.3 shuffle寫
shuffle過程需要將中間產生的臨時結果記錄在文件中
Map過程之後需要shuffle寫
在spark早期版本中,臨時文件個數map*reduce個數(同時打開文件越多,讀寫性能越低)
在新的版本中,臨時文件個數爲reduce個數,但多了一個索引文件*.index(多了排序過程)
在spark.shuffle.manager 配置
5.4 shuffle讀
shuffle讀是reduce階段,需要發起IO操作,如果是不同節點,需要發起網路IO
將臨時文件讀到RDD中
5.6 總結
spark的shuffle過程會影響性能,沒有shuffle性能會提高很多
6 stage
寬依賴和窄依賴合理劃分爲stage,有效的利用流水線思想
分成有向無環圖DAG
不同的stage之間肯定會有一次shuffle運算
同一個stage內部,肯定沒有shuffle運算,充分利用內存,臨時文件不需要落地
7 spark streaming
用來處理流式數據,經常用於實時數據分析
就是按照時間段手機數據,把一個時間段之內的數據封裝爲DStream類型的RDD,將DStream交給spark進行處理
[root@slave1 bin]# ./spark-shell --master=local[2]
在啓動spark shell時候單機模式下至少需要兩個線程,集羣環境下每個worker至少兩core
其中一個線程用來收集數據,另一個線程用來計算
7.1 例子:從文件中讀取流數據(無狀態)
scala> import org.apache.spark._
scala> import org.apache.spark.streaming._
scala> import org.apache.spark.streaming.StreamingContext._
scala> var scc = new StreamingContext(sc,Seconds(10))
scala> var ds = scc.textFileStream("file:///root/temp")
//scala> var ds = scc.textFileStream("hdfs://master:9000/user")
scala> ds.map{x=>(x,1)}.reduceByKey{(x,y)=>x+y}.print
scala> scc.start
8 spark性能調優
8.1 序列化方式
數據傳輸(網絡傳輸和本地傳輸)、緩存
默認使用java的序列化機制(速度慢,字節量大)
Kryo序列化方式解決java序列化機制的缺點(在配置文件中進行修改)
8.2 內存
儘可能使用基本數據類型,Integer對 象比int多了16字節的對象頭
8.3 RDD調優
可以通過配置文件配置worker的內存大小
RDD默認情況下,計算內存佔用40%,緩存使用60%
可以通過配置文件配置改比例
8.4 並行度調優
每個worker的core最理想的與實際物理機的CPU核數相同
數據分區的數
分區數過少,可能會造成worker內存溢出
分區數過多,會造成任務數大,網絡傳輸耗時
8.5 使用廣播變量
某一個RDD頻繁使用,將RDD廣播到每一個worker上
數據字典,將RDD作爲數據標準集
8.6 shuffle過程
配置shuffle寫的路徑爲一組磁盤,將不同的磁盤掛載到不同的硬盤上,並行提升IO操作
spark.local.dir=/mnt1/spark,/mnt2/spark,/mnt3/spark