spark
spark 概述
一. spark和hadoop
MapReduce | Spark |
---|---|
數據存儲結構:磁盤HDFS文件系統的split | 使用內存構建彈性分佈式數據集RDDs對數據進行運算和cache |
編程範式:Map + Reduce | DAG: Transformation + Action |
計算中間結果落到磁盤IO及序列化、反序列化代價大 | 計算中間結果在內存中維護存取速度比磁盤高几個數量級 |
Task以進程的方式維護,需要數秒時間才能啓動任務 | Task以線程的方式維護對於小數據集讀取能夠達到亞秒級的延遲 |
hadoop缺點:
1.表達能力有限(MapReduce)
2.磁盤IO開銷大(shuffle)
3.延遲高
spark:
1.Spark的計算模式屬於MapReduce,在借鑑Hadoop MapReduce優點的同時很好地解決了MapReduce所面臨的問題
2.不侷限於Map和Reduce操作,還提供了多種數據集操作類型,編程模型比Hadoop MapReduce更靈活
3.Spark提供了內存計算,可將中間結果放到內存中,對於迭代運算效率更高
4.Spark基於DAG的任務調度執行機制,要優於Hadoop MapReduce的迭代執行機制(函數調用)
使用Hadoop進行迭代計算非常耗資源;
Spark將數據載入內存後,之後的迭代計算都可以直接使用內存中的中間結果作運算,避免了從磁盤中頻繁讀取數據
二. 應用常景和解決
在實際應用中,大數據處理主要包括以下三個類型:
1.複雜的批量數據處理:
通常時間跨度在數十分鐘到數小時之間
2.基於歷史數據的交互式查詢:
通常時間跨度在數十秒到數分鐘之間
3.基於實時數據流的數據處理:
通常時間跨度在數百毫秒到數秒之間
當同時存在以上三種場景時,就需要同時部署三種不同的軟件比如:
MapReduce:離線批處理
Impala:交互式查詢處理
Storm:實時流處理
這樣做難免會帶來一些問題:
不同場景之間輸入輸出數據無法做到無縫共享,通常需要進行數據格式的轉換
不同的軟件需要不同的開發和維護團隊,帶來了較高的使用成本
比較難以對同一個集羣中的各個系統進行統一的資源協調和分配
Spark:既能夠提供內存計算框架,也可以支持SQL即席查詢、實時流式計算、機器學習和圖計算等
Spark可以部署在資源管理器YARN之上,提供一站式的大數據解決方案
Spark所提供的生態系統足以應對上述三種場景,即同時支持批處理、交互式查詢和流數據處理
生態系統組件
Spark的生態系統主要包含了Spark Core、Spark SQL、Spark Streaming、MLLib和GraphX 等組件。
應用場景
應用場景 | 時間跨度 | 其他框架 | Spark生態系統組件 |
---|---|---|---|
複雜的批量數據處理 | 小時級 | MapReduce | Hive Spark |
基於歷史數據的交互式查詢 | 分鐘級、秒級 | Impala、Dremel、Drill | Spark SQL |
基於實時數據流的數據處理 | 毫秒、秒級 | Storm、S4 | Spark Streaming |
基於歷史數據的數據挖掘 | - | Mahout | MLlib |
圖結構數據的處理 | - | Pregel、Hama | GraphX |
Spark執行任務流程圖
1、Spark運行架構包括:Master(集羣資源管理)、Slaves(運行任務的工作節點)、應用程序的控制節點(Driver)和每個工作節點上負責任務的執行進程(Executor);
2、Master是集羣資源的管理者(Cluster Manager)。支持:Standalone,Yarn,Mesos;
3、Slaves在spark中被稱爲Worker,工作節點,包括Executor。;
4、Driver Program。該進程運行應用的 main() 方法並且創建了SparkContext。由Cluster Manager分配資源,SparkContext將發送Task到Executor上執行。
5、每個工作節點上負責任務的執行進程(Executor);
Executor包括cache、分配到Executor上的task任務(task1、task2…tasksN)
三. Spark安裝
1.從https://spark.apache.org/獲得Spark的安裝包
2.解壓並安裝Spark
tar –zxvf spark-****-bin-hadoop2.7.tgz
3.配置Spark
在YARN平臺上運行Spark需要配置HADOOP_CONF_DIR、YARN_CONF_DIR和HDFS_CONF_DIR環境變量
3.1 vim /etc/profile
export HADOOP_CONF_DIR=$HADOOP_HOME/home/lyb/hadoop
export HDFS_CONF_DIR=$HADOOP_HOME/home/lyb/hadoop
export YARN_CONF_DIR=$HADOOP_HOME/home/lyb/hadoop
保存關閉後執行
3.2 source /etc/profile
使環境變量生效
3.3 修改spark-env.sh
cp spark-env.sh.tmplate spark-env.sh
vim spark-env.sh
JAVA_HOME=/home/lyb/jdk
4.驗證Spark安裝
計算圓周率PI的值
進入Spark安裝主目錄
./bin/spark-submit
--class org.apache.spark.examples.SparkPi
--master yarn-cluster 模式選擇(yarn-client;local)
--num-executors 3 進程數
--driver-memory 1g 驅動內存
--executor-memory 1g 運行時內存
--executor-cores 1 核數
/home/lyb/spark/examples/jars/spark-examples*.jar 10
四. Spark部署模式
1、單機本地模式(Spark所有進程都運行在一臺機器的JVM中)
local:本地模式。在本地啓動一個線程來運行作業;
local[N]:也是本地模式。啓動了N個線程;
local[*]:還是本地模式。用了系統中所有的核;
local[N,M]:第一個參數表示用到核的個數;第二個參數表示容許該 作業失敗 的次數。上面的幾種模式沒有指定M參數,其默認值都是1;
2、僞分佈式模式 (在一臺機器中模擬集羣運行,相關的進程在同一臺機器上)。
local-cluster[N, cores, memory]:僞分佈式模式。N模擬集羣的Slave節點個數;cores模擬集羣中各個Slave節點上的內核數;memory模擬集羣的各個Slave節點上的內存大小.
3、分佈式模式包括:Spark自帶的 Standalone、Yarn、Mesos。
spark:// :Spark的Standalone模式;
yarn:YARN模式;
(mesos|zk) : //:Mesos模式;
simr://:simr是Spark In MapReduce的縮寫。在MapReduce 1中是沒有 YARN的,如果要在MapReduce 中使用Spark,就使用這種模式。
3.1 Spark On yarn模式
1、Spark On yarn模式。是一種最有前景的部署模式。但限於YARN自身的發展,目前僅支持粗粒度模式(Coarse-grained Mode);
2、由於YARN上的Container資源是不可以動態伸縮的,一旦Container啓動之後,可使用的資源不能再發生變化;
3、YARN擁有強大的社區支持,且逐步已經成爲大數據集羣資源管理系統的標準;
4、spark on yarn 的支持兩種模式:
yarn-cluster:適用於生產環境
yarn-client:適用於交互、調試,希望立即看到app的輸出
1.Spark支持資源動態共享,運行於Yarn的框架都共享一個集中配置好的資源池
2.可以很方便的利用Yarn的資源調度特性來做分類·,隔離以及優先級控制負載,
擁有更靈活的調度策略
3.Yarn可以自由地選擇executor數量
4.Yarn是唯一支持Spark安全的集羣管理器,使用Yarn,Spark可以運行於Kerberized Hadoop
之上,在它們進程之間進行安全認證
yarn-client和yarn-cluster的區別:
1)yarn-cluster:適用於生產環境;
2)yarn-client:適用於交互、調試,希望立即看到應用程序的輸出
3)SparkContext初始化不同,這也導致了Driver所在位置的不同,YarnCluster
的Driver是在集羣的某一臺NM上,但是Yarn-Client就是在RM在機器上;
4)而Driver會和Executors進行通信,這也導致了Yarn_cluster在提交App之後可
以關閉Client,而Yarn-Client不可以;
5) Client結果當場就可看到,而cluster則需要到hadoop/logs/userlogs下找或者
自己配置的logs路徑下
3.2 Standalone:spark://主機名:port
standalone模式,即獨立模式,自帶完整的服務,可單獨部署到一個集羣中,無需依賴任何其他資源管理系統。從一定程度上說,該模式是其他兩種的基礎。
standalone-cluster:適用於生產環境
standalone-client:默認模式。適用於交互、調試,希望立即看到app的輸出
是spark自己實現的,它是一個資源調度框架。
運行流程:
1)當spark集羣啓動以後,worker節點會有一個心跳機制和master保持通信;
2)SparkContext連接到master以後會向master申請資源,而master會根據worker
心跳來分配worker的資源,並啓動worker的executor進程;
3)SparkContext將程序代碼解析成dag結構,並提交給DagScheduler;
DAGScheduler:負責分析用戶提交的應用,並根據計算任務的依賴關係建立DAG,
且將DAG劃分爲不同的Stage,每個Stage可併發執行一組task。
注:DAG在不同的資源管理框架實現是一樣的。
一個Job會被拆分爲多組Task,每組任務被稱爲一個Stage就像Map Stage,Reduce Stage
4)dag會在DagScheduler中分解成很多stage,每個stage包含着多個task;
5)stage會被提交給TaskScheduler,而TaskScheduler會將task分配到worker,提交
給executor進程,executor進程會創建線程池去執行task,並且向SparkContext
報告執行情況,直到task完成;
6)所有task完成以後,SparkContext向Master註銷並釋放資源;
總結:
standalone的是spark默認的運行模式,它的運行流程主要就是把程序代碼解析成dag
結構,並再細分到各個task提交給executor線程池去並行計算。
在運行流程中我們並沒有提到job這個概念,只是說dag結構會被分解成很多的stage。
其實,分解過程中如果遇到action操作(這不暫時不關注action操作是什麼),那麼
就會生成一個job,而每一個job都包含着一個或者多個stage,所以job和stage也是
一個總分的邏輯關係。
3.2.1 Standalone 配置
1.修改配置
1)修改spark-env.sh
SPARK_MASTER_HOST=master
//主節點host名稱
SPARK_MASTER_PORT=7077
//spark傳輸端口號
SPARK_WORKER_CORES=2
// 分配給每個Worker core的個數
SPARK_WORKER_MEMORY=2g
// 分配給每個Worker內存的數量
SPARK_DAEMON_MEMORY=1g
//配給服務器的內存
SPARK_WORKER_INSTANCES=3
//實例數(一臺虛擬機默認一個worker實例但配完後每臺就有幾個worker)
//從節點的worker數
HADOOP_CONF_DIR=$HADOOP_HOME/etc/hadoop
//如果有這一項spark-shell啓動是會檢查hadoop的相關配置
//但如果環境變量配置了就不用配置了
2)修改spark-default.conf
spark.master spark://master:7077
//訪問地址
spark.eventLog.dir hdfs://namenode:8021/directory
//日誌地址路徑
spark.serializer org.apache.spark.serializer.KryoSerializer
//序列化
spark.driver.memory 1g
//diver內存
spark.cores.max=6
//核心最大數
//當超過時會kill 將要運行的Standalone的executor
3)修改slaves
slave1
slave2
//這裏面寫的是從節點的節點主機名稱
//worker所在節點主機
2.啓動
//儘量在spark/sbin啓動start-all.sh
//因爲這裏的start-all.sh與hadoop啓動的腳本相同
//雖然說是根據Path路徑順序來但會衝突
注意:啓動前先啓動hadoop
spark/sbin/start-all.sh
當在slave1和slave2上看到每個節點都有3個worker時就成功了
webUI:
master:8080
//master需要在本機上配置c:windows/system32/Driver/etc/hosts
3.2.2 Standalone有兩種模式
3.測試
Standalone有兩種模式:
Standalone-client模式
Standalone-cluster模式
spark-submit --master spark://master:7077
--class org.apache.spark.examples.SparkPi jar地址 main函數需要參數
//不寫默認client模式
spark-submit --master spark://master:7077
--deploy-mode client //依靠
--class org.apache.spark.examples.SparkPi jar地址 100
1.client模式適用於測試調試程序。Driver進程是在客戶端啓動的,這裏的客戶端就是指提交應用程序的當前節點。
在Driver端可以看到task執行的情況。生產環境下不能使用client模式,是因爲:假設要提交100個application到集羣運行
Driver每次都會在client端啓動,那麼就會導致客戶端100次網卡流量暴增的問題。
(因爲要監控task的運行情況,會佔用很多端口,如上圖的結果圖)客戶端網卡通信,都被task監控信息佔用。
spark-submit --master spark://master:7077
--deploy-mode cluster
--class org.apache.spark.examples.SparkPi jar路徑 100
1.當在客戶端提交多個application時,Driver會在Woker節點上隨機啓動,這種模式會將單節點的網卡流量激增問題分散到集羣中。
在客戶端看不到task執行情況和結果。要去webui中看。
2.cluster模式適用於生產環境
3.Master模式先啓動Driver,再啓動Application。
運行時可以在
master:8080 查看進度
3.3 Mesos模式
Spark On Mesos模式。也是很多公司採用的模式,官方推薦這種模式。Spark開發之初就考慮到支持Mesos,因此,目前而言,Spark運行在Mesos上會比運行在YARN上更加靈活,更加自然;
目前在Spark On Mesos環境中,用戶可選擇兩種調度模式之一運行自己的應用程序:
粗粒度模式(Coarse-grained Mode):每個應用程序的運行環境由一個Dirver和若干個Executor組成,其中,每個Executor佔用若干資源,內部可運行多個Task(對應多少個“slot”)。應用程序的各個任務正式運行之前,需要將運行環境中的資源全部申請好,且運行過程中要一直佔用這些資源,即使不用,最後程序運行結束後,回收這些資源。
細粒度模式(Fine-grained Mode):鑑於粗粒度模式會造成大量資源浪費,Spark On Mesos還提供了另外一種調度模式:細粒度模式,這種模式類似於現在的雲計算,思想是按需分配
4、Spark專業術語
五.spark-submit 詳解
Options:
--master MASTER_URL
spark://host:port, mesos://host:port, yarn, or local.
--deploy-mode DEPLOY_MODE
driver運行之處,client運行在本機,cluster運行在集羣
--class CLASS_NAME
應用程序包的要運行的class
--name NAME
應用程序名稱
--jars JARS
用逗號隔開的driver本地jar包列表以及executor類路徑
--py-files PY_FILES
用逗號隔開的放置在Python應用程序PYTHONPATH上的.zip, .egg, .py文件列表
--files FILES
用逗號隔開的要放置在每個executor工作目錄的文件列表
--properties-file FILE
設置應用程序屬性的文件放置位置,默認是conf/spark-defaults.conf
--driver-memory MEM
driver內存大小,默認512M
--driver-java-options
driver的java選項
--driver-library-path
driver的庫路徑Extra library path entries to pass to the driver
--driver-class-path
driver的類路徑,用--jars 添加的jar包會自動包含在類路徑裏
--executor-memory MEM
executor內存大小,默認1G
Spark standalone with cluster deploy mode only:
–driver-cores NUM
driver使用內核數,默認爲1
–supervise
如果設置了該參數,driver失敗是會重啓
Spark standalone and Mesos only:
–total-executor-cores NUM
executor使用的總核數
YARN-only:
–executor-cores NUM
每個executor使用的內核數,默認爲1
–queue QUEUE_NAME
提交應用程序給哪個YARN的隊列,默認是default隊列
–num-executors NUM
啓動的executor數量,默認是2個
–archives ARCHIVES
被每個executor提取到工作目錄的檔案列表,用逗號隔開
六.Spark啓停命令
1、在主節點啓動所有服務(包括slave節點,需要做免密碼登錄)
start-all.sh stop-all.sh
與hadoop的命令有衝突,需要調整
2、逐一啓動主節點、從節點(在不同的節點上發指令)
start-master.sh | stop-master.sh
start-slave.sh spark://node1:7077
3、一次啓停全部的從節點
start-slaves.sh | stop-slaves.sh
備註:
以上命令成對出現,有start一般就有stop
4、spark-daemon.sh
spark-daemon.sh start org.apache.spark.deploy.master.Master
spark-daemon.sh stop org.apache.spark.deploy.master.Master
spark-daemon.sh status org.apache.spark.deploy.master.Master
備註:很少使用
Spark webUI 及 History Server
1、能在主從節點啓動相應服務(啓動後用jps檢查)
start-dfs.sh / stop-dfs.sh
start-all.sh / stop-all.sh
2、spark的日誌文件
缺省位置$SPARK_HOME/logs/
3、進入spark-shell,執行命令
4、Web UI
http://hostIp:8080/
不要從windows的IE中連接linux主機查看。就在Linux環境中查看
5、run example
run-example SparkPi 10
需要啓動hdfs、spark;同時檢查二者的安裝是否正確
啓動Spark集羣
cd $SPARK_HOME/sbin
使用start-all.sh、stop-all.sh命令來啓動/停止Spark集羣
啓動之後在master主節點運行的Spark守護進程爲:
Master(一個)
在slaves從節點運行的守護進程爲:
Worker
每個從節點運行的worker進程個數根據設置的SPARK_WORKER_INSTANCES=3 實例個數決定,集羣中的worker個數爲從節點的數量乘以worker實例的個數,此處爲 2 * 3共6個,相應的cores的個數,根據SPARK_WORKER_CORES=2 就是:6 * 2 共12個。
此處注意:
因爲啓動Spark集羣之前,已經啓動了Hadoop集羣,hadoop集羣的啓停命令也有start-all.sh / stop-all.sh,所以啓動了hadoop之後需要再啓動Spark需要切換到Spark的主目錄的sbin路徑下運行相應的啓停命令,防止對hadoop集羣造成影響。
七.spark shell
進入spark-shell
啓動Spark集羣之後,可以使用spark-shell命令進入Spark的交互式窗口進行Spark的操作。
啓動spark-shell命令
spark-shell --master 模式名稱
--name application的名字
......
與submit參數類似
模式分爲:local[Tasknum]
yarn
spark://master:7077
1、spark-shell本地單機模式
spark-shell --master local[2]
相當於使用spark-submit命令提交了一個spark進程,使用jps命令可以看到,開啓了一個SparkSubmit的守護進程。
2、spark-shell sparkalone模式
spark-shell --master spark://master200:7077
3、spark-shell on yarn模式
spark-shell --master yarn
4、spark-shell操作練習
shell:交互式運行spark代碼,類似於scala交互式終端
可用於快速體驗spark,查看程序運行結果.
// 在使用spark-shell進入的時候就創建的SparkContext的實例對象sc、SparkSession實例對象spark
scala> sc
res0: org.apache.spark.SparkContext = org.apache.spark.SparkContext@54f69311
scala> spark
res0: org.apache.spark.sql.SparkSession = org.apache.spark.sql.SparkSession@663622b1
// 使用sc.parallelize()方法將一般的數據類型轉爲RDDs的數據集
scala> val nums = sc.parallelize(List(1,2,3,4,5))
nums: org.apache.spark.rdd.RDD[Int] = ParallelCollectionRDD[0] at parallelize at < console>:24
scala> nums.count()
res1: Long = 5
scala> nums.take(3)
res2: Array[Int] = Array(1, 2, 3)
scala> val words = sc.parallelize(List(“Hello, this is my spark shell program.”, “Hello, this is my book”, “spark shell”))
words: org.apache.spark.rdd.RDD[String] = ParallelCollectionRDD[0] at parallelize at < console > : 24
scala> words.flatMap(.split(" ")).map((,1)).reduceByKey(+).collect()
res14: Array[(String, Int)] = Array((this,2), (program.,1), (is,2), (my,2), (shell,2), (Hello,2), (book,1), (spark,2))
4.1讀取HDFS文件系統
val rdd2 = sc.textFile("hdfs://master:9000/words.txt")
讀取本地文件
val rdd2 = sc.textFile(“file:///root/words.txt”)
//在哪存儲二進制格式
.saveAsSequenceFile("存儲路徑")
.saveAsTextFile("存儲路徑") //txt格式