spark系列之一

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       

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章