Spark版本
cdh5.9.0集成的spark的版本1.6.0,集成的hadoop版本2.6.0。查看的網址:
http://archive.cloudera.com/cdh5/redhat/6/x86_64/cdh/5.9.0/
如果用cdh5.9.0 parcels離線安裝自帶的spark(on yarn),啓動時提示缺少包,需要修改spark-env.sh的配置SPARK_DIST_CLASSPATH,裏面默認的配置爲在線用rpm方式安裝的配置,修改爲/opt/clouderra/parcels/CDH/lib。
Spark運行模式
Spark 的執行模式有 local、Yarn、Standalone、Mesos四類。
開發和測試用 local 模式,其實就是用多線程模似分佈式執行。
如果業務部門較少且不需要對部門或組之間的資源做劃分和優先級調度的話,可以使用 Standalone 模式來部署。
當如果有多個部門或組,且希望每個組織可以限制固定運行的最大資源,另外組或者任務需要有優先級執行的話,可以選擇 Yarn 或 Mesos。
Standalone模式,即獨立模式,master/slave(worker),自帶完整的服務,可單獨部署到一個集羣中,無需依賴任何其他資源管理系統。需要啓動Master和Worker守護進程,即服務端進程,就好比Mapreduce的JobTracker和TaskTracker。
Spark on Yarn: 把Spark作業的調度和資源分配交給Yarn,Yarn相當於Spark集羣的Master,Spark無自己的守護進程,僅僅作爲客戶端存在。
MR(Hive)、Storm、Tez、Spark,期望這些作業有統一的調度和資源分配的角色,Yarn(MR2)。
Spark組件
Cluster Manager:在Standalone模式中即爲Master(主節點),控制整個集羣,監控Worker。在YARN模式中爲資源管理器。
Worker:從節點,負責控制計算節點,啓動Executor或Driver。在YARN模式中爲NodeManager,負責計算節點的控制。
Driver:運行Application的main()函數並創建SparkContext。
Executor:執行器,在worker node上執行任務的組件、用於啓動線程池運行任務。
SparkContext:整個應用的上下文,控制應用的生命週期,提交作業的入口。
RDD:Spark的基本計算單元,一組RDD可形成執行的有向無環圖RDD Graph。
DAG Scheduler:實現將Spark作業分解成一到多個Stage,每個Stage根據RDD的Partition個數決定Task的個數,然後生成相應的Task set放到TaskScheduler(NodeManager)中。
TaskScheduler:將任務(Task)分發給Executor執行。
Stage:一個Spark作業一般包含一到多個Stage。
Task:一個Stage包含一到多個Task,通過多個Task實現並行運行的功能。
Spark集羣部署
配置免密鑰登錄,
CDH中用CM進行集羣管理,集羣直接互聯是通過ssh協議,但我們不需要配置ssh免密匙訪問,因爲CM中配置了通過相同帳戶密碼訪問。用Apache Spark的話,必須配置ssh免密匙訪問。
安裝Scala和Spark,
修改環境變量,
1vi /etc/profile
2export HADOOP_HOME=/opt/cloudera/parcels/CDH/lib/hadoop
3export SPARK_HOME=/opt/soft/spark2.0/spark-2.2.0-bin-hadoop2.6
4export SCALA_HOME=/opt/soft/spark2.0/scala-2.11.8
5export JAVA_HOME=/opt/soft/jdk1.8.0_131
6export HADOOP_CONF_DIR=/etc/hadoop/conf
修改$SPARK_HOME/conf,
mv slaves.template slaves,slaves裏配置工作節點主機名列表。
mv spark-env.sh.template spark-env.sh,spark-env.sh配置一些環境變量,由於我們用Yarn模式,這裏面不用配置。如果是standalone模式呢?
分佈式模式運行測試,
1spark-submit --class org.apache.spark.examples.SparkPi \
2--master yarn \
3--num-executors 1 \
4--driver-memory 1g \
5--executor-memory 1g \
6--executor-cores 1 \
7--conf "spark.app.name=SparkPi" \
8/export/servers/spark-2.0.2-bin-hadoop2.6/examples/jars/spark-examples_2.11-2.0.2.jar
報錯信息,設置HADOOP_CONF_DIR環境變量即可。
1Exception in thread "main" java.lang.Exception: When running with master 'yarn' either HADOOP_CONF_DIR or YARN_CONF_DIR must be set in the environment.
2 at org.apache.spark.deploy.SparkSubmitArguments.validateSubmitArguments(SparkSubmitArguments.scala:256)
3 at org.apache.spark.deploy.SparkSubmitArguments.validateArguments(SparkSubmitArguments.scala:233)
4 at org.apache.spark.deploy.SparkSubmitArguments.<init>(SparkSubmitArguments.scala:110)
5 at org.apache.spark.deploy.SparkSubmit$.main(SparkSubmit.scala:117)
6 at org.apache.spark.deploy.SparkSubmit.main(SparkSubmit.scala)
如果內存不足,報錯的話,在cm裏進行yarn的配置,如下2個設置爲2g:
yarn.scheduler.maximum-allocation-mb、yarn.nodemanager.resource.memory-mb,
保存後,部署客戶端配置,把cm界面裏修改過的參數同步到每個節點的xml配置文件裏,重啓Yarn服務。
RDD
Spark 對數據的核心抽象——彈性分佈式數據集(Resilient Distributed Dataset,簡稱RDD)。在Spark 中,對數據的所有操作不外乎創建RDD和操作RDD 。
對數據(Seq)的操作,比如List:轉換(Transform),map、filter,返回List類型,數據轉換/加工過程。Action:head、tail、count ,返回不同類型,即我們需要的結果。
RDD就是類似集合類(Iterable),具有和集合類幾乎完全相同的操作(Transform和Action)。而在這一切背後,Spark 會自動將RDD 中的數據分發到集羣上,並將操作並行化執行。
Spark中的RDD就是一個不可變的分佈式對象集合。每個RDD 都被分爲多個分區,這些分區運行在集羣中的不同節點上。RDD 可以包含Python、Java、Scala 中任意類型的對象,甚至可以包含用戶自定義的對象。
RDD是類似Iterable的數據結構。
idea中進行spark core開發,需要在工程中新建一個lib目錄,把spark的包複製進去,在Project Structure中的Libraries中把包加進來。
創建RDD
用戶可以使用兩種方法創建RDD:
用SparkContext的parallelize(Seq)把Seq轉爲RDD。該方式常用於學習和實驗。
讀外部數據,通常是讀HDFS、消息隊列等。
1def parallelize[T](seq: Seq[T], numSlices: Int = defaultParallelism) : RDD[T]
numSlices是並行度,具有初始值所以調用時可以只給一個參數。比如可以parallelize(seq),可以parallelize(seq,10),並行度爲10意味着Spark把數據分割爲10份,放在集羣上運行。defaultParallelism是機器CPU個數。
1# 查看CPU的個數
2cat /proc/cpuinfo| grep "processor"| wc -l
RDD的操作
RDD有兩種類型的操作:Transform操作和Action操作。注:就是Iterable類中的函數,Transform返回Iterable本身類型,Action返回新類型。
Iterable: Seq、Map
對應到
RDD:單元素RDD、PairRDD
Transform操作會由一個RDD生成一個新的RDD,這個過程中不進行實質計算,只有當第一次Action操作時纔會真正計算。稱作Lazy計算,惰性計算。
Action操作會對RDD計算出一個結果,可以把結果返回,或把結果存儲到外部存儲系統(如HDFS)中。
RDD是類似Iterable的數據結構,也具有Iterable類的Map()、filter()、flatMap()等高階函數。
Action操作,
collect():把數據返回驅動器程序中最簡單、最常見的操作, 通常在單元測試中使用,數據量不能太大,因爲放在內存中,數據量大會內存溢出。
reduce():類似sum(),如:val sum = rdd.reduce((x, y) => x + y),結果同sum。
fold():和reduce()類似,多一個“初始值”,當初始值爲零時效果同reduce()。fold(0) = reduce()
take(n):返回RDD中的n個元素,並且嘗試只訪問儘量少的分區。
top(n):從RDD中獲取前幾個元素。
count():用來返回元素的個數。
countByValue():返回一個從各值到值對應的計數的映射表。
sum():返回彙總。
fold(n)的執行原理:每個分區裏進行這樣的計算:初始值+sum(元素),最後進行:初始值+sum(分區sum值),初始值累加次數爲分區數+1次。