RDD的處理方法(創建、轉換、行動、分區)

spark生態系統:底層是spark core,在spark core的基礎上開發了其他組件,可以支持不同的應用場景。spark sql支持sql 查詢,spark streaming可以支持流計算,spark mLlib支持機器學習等。

rdd編程是指spark core(底層)的編程。爲什麼叫rdd編程?因爲整個過程就是對rdd的一次又一次的轉換。

 

rdd編程基礎

1、rdd創建方法

現有兩種方法創建rdd:通過文件系統中加載數據創建rdd,通過並行集合(數組)來創建rdd。

1、通過文件系統加載數據創建rdd

textfile()支持的數據類型:

分佈式文件系統HDFS;本地文件系統;雲端文件如Amazon S3等

假設現有文檔word.txt有三行記錄,經過sc.textfile()加載,就生成了上圖右側的RDD,RDD的名稱爲lines,該RDD包含了三個元素,每個元素對應了文本文件的一行,所以加載後的RDD每個元素是字符串類型。

參看RDD中元素,可使用高階函數foreach方法,裏面傳遞一個函數作爲它的參數,此處傳遞的是print函數。

hdfs後面是兩個斜槓,localhost是主機名,9000爲安裝hadoop的端口號

在linux系統中,有個主目錄,若用hadoop用戶名登錄linux系統,那麼linux系統會自動爲hadoop用戶創建一個主目錄\home\hadoop,簡約用~表示。同理在分佈式文件系統hdfs中,也存在一個當前用戶的用戶主目錄,該主目錄爲/user/hadoop.

 

2、並行集合(數組)創建rdd

 

2、RDD操作(轉換操作filter、map、flatmap)

將健封裝在用pyspark.resultiterable.ResultIterable對象中

reducebykey相當於先用groupbykey進行操作,得到結果後再執行lambda函數的操作。

 

3、RDD操作(行動操作)

 

4、持久化

對於迭代計算,經常需要多次重複使用同一組數據,持久化可以將多次訪問的值保存在內存中,不消失,下次再重複使用的時候就需要從頭到尾的計算了。

peisist()

persist(memory_only):將RDD作爲反序列化對象存在JVM當中,如果內存不足,就按LRU(litte recently use)原則(最近最少使用原則)原則替換內存(僅存在內存當中)。

persist(memory_and_disk):同時保存在內存和磁盤。優先保存內存,若內存不足,再將多餘的存入磁盤。

在實際工作中,我們都常使用保存在內存中,對於persist(memory_only)有一個簡介的方法:.cache()方法

我們知道當內存中東西太多會降低電腦的速率的,所以當我們使用完並確保後續不在使用之前計算的RDD時,我們需要將該RDD從內存中刪除。

 

5、RDD分區

RDD分區的好處:1、能夠增加並行度,即並行計算;2、減少通信開銷

userData表是一個非常龐大的表,有成百上千萬的用戶,每個用戶均有一個userID和userInfo。events表是一個小表,包含兩個字段,分別爲userID和LinkInfo,記錄了這些用戶在過去的五分鐘之內所訪問的網站的鏈接信息,比如userID爲1的用戶,訪問了新浪網,userID爲2的用戶,訪問了阿里巴巴網,即events記錄了每個用戶訪問的鏈接信息。

若我們希望找到用戶的名字、單位、訪問了什麼網站,則需要將UserData與events連接起來。這兩表的連接就關係到分區的問題。

假設沒有分區去做連接,對於userData,數據非常大的時候,數據需要分塊存儲(注:不是分區),即數據在一臺機器上存儲不了,需要分塊,分塊保存在不同機器上,如上圖所示的u1塊、u2塊、u3塊等,每塊都分佈在不同的機器上。假設有一千萬用戶,這時候u1、u2、u3塊等的userID均散佈在0至一千萬之間(因爲不是分區,而是分塊,每塊的用戶信息都是散佈在0至一千萬之間)。這時候連接採用了一箇中間機器,讓j1機器負責0至100萬的連接,j2機器負責100萬到200的連接,以此類推。此時將u1塊中0-100萬的userID呈給j1,100萬-200萬的userID呈給j2等,同理針對u2塊......。如此這樣就會發生如上圖所示的大量數據的交叉傳輸,這就是涉及非常昂貴的通信開銷。

                               

若採取分區處理,如上圖所示,讓u1只保存0-100萬的userID信息,u2只保存100-200萬的userID信息,以此類推。如此再與中間機器連接時,按分區後的表進行連接,從而節省了大量數據傳輸開銷。

 

分區的原則:

分區的個數 儘量等於 集羣中CPU核心數目,每個分區啓動一個線程

對於不同的spark部署模式而言,可通過設置具體參數值,來配置默認的分區數目,參數名爲spark.default.parallelism。

一般而言,local模式,默認爲本地機器的CPU數目,若設置了local[N],則默認爲N;

對於Apache Mesos模式,默認分區數目爲8;

對於Standalone模式和YARN模式,是將集羣中所有CPU核心數目總和與2之間取較大值作爲分區的默認數目。

 

如何設置分區個數?

創建時手動指定分區個數:在調用textFile()和parallelize()方式時,可以人工的設定它的分區個數。

 

自定義分區

spark有哈希分區(HashPartitioner)、區域分區(RangePartitioner)以及自定義分區,自定義分區有時候可進一步減少通信開銷,那如何自定義分區呢?

現有實例如下:

要實現如上的分區,需要自定義分區的函數:

.partitionBy是一個重分區的方法,其中參數10表示將要分區的分區個數,MyPartitioner是我們自定義的分區類。partitionBy只接受鍵值對類型,根據鍵值對中鍵進行分區。

 

6、綜合案例(詞頻統計)

代碼如下(單機):

代碼運行過程:

    

多機並行執行

此時需要一個集羣進行詞頻統計,將Hadoop和spark同時部署在同一個集羣裏面,我們將集羣當中的某個節點既作爲HDFS的存儲節點,也作爲Spark的worknode,工作節點,即Hadoop的存儲組件和Spark的計算組件是放在了同一臺機器上的,如上圖所示。如此則可以讓Spark對保存在HDFS當中的詞頻文件進行並行的詞頻統計,最終將結果進行彙總。

下圖詳細描述了分佈式詞頻統計的過程。

 

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