爲啥要學Spark中的RDD??
RDD的全稱叫做Resilient Distributed Datasets,即彈性分佈式數據集。
之前我們學過MapReduce,它具有自動容錯、平衡負載和可拓展性的優點,但是其最大缺點是採用非循環式的數據流模型,使得在迭代計算式要進行大量的磁盤IO操作。Spark中的RDD可以很好的解決這一缺點。
如何理解RDD ------------> 可以將RDD理解爲一個分佈式存儲在集羣中的大型數據集合,不同RDD之間可以通過轉換操作形成依賴關係實現管道化,從而避免了中間結果的I/O操作,提高數據處理的速度和性能。
RDD是一個彈性可復原的分佈式數據集!
RDD是一個邏輯概念,一個RDD中有多個分區,一個分區在Executor節點上執行時,他就是一個迭代器。
一個RDD有多個分區,一個分區肯定在一臺機器上,但是一臺機器可以有多個分區,我們要操作的是分佈在多臺機器上的數據,而RDD相當於是一個代理,對RDD進行操作其實就是對分區進行操作,就是對每一臺機器上的迭代器進行操作,因爲迭代器引用着我們要操作的數據!
還是不懂啥是RDD? 看這個試試 請用通俗形象的語言解釋下:Spark中的RDD到底是什麼意思? spark——spark中常說RDD,究竟RDD是什麼?
五大特點:
1. RDD的創建
我們通過Spark中的SparkContext對象調用textFile()方法加載數據創建RDD。(首先啓動Spark集羣,hadoop集羣 一個是在spark下的bin裏啓動start-all.sh 一個是隨便啓動start.all-sh)
①通過本地文件創建RDD
啓動Spark-shell 輸入:/export/servers/spark/bin/spark-shell --master local[1]
從文件系統中加載 我在這個路徑下創建了一個txt /export/data/temp/words.txt 導進去
②從文件系統中加載數據創建RDD
從hdfs上加載 剛纔沒開hadoop集羣的現在開,並且重啓spark服務
這次從hdfs上加載 輸入:/export/servers/spark/bin/spark-shell --master spark://hadoop01:7077
從hadoop上拿東西下來 我的hadoop在 spark/input/words.txt 有文件(注意hadoop與文件系統的區別 文件系統有file://)
③通過並行方式創建RDD(建一個數組,通過數組建)
2.RDD處理過程
Spark用Scala語言實現了RDD的API,程序開發者可以通過調用API對RDD進行操作處理。RDD經過一系列的“轉換”操作,每一次轉換都會產生不同的RDD,以供給下一次“轉換”操作使用,直到最後一個RDD經過“行動”操作纔會被真正計算處理,並輸出到外部數據源中,若是中間的數據結果需要複用,則可以進行緩存處理,將數據緩存到內存中。
轉換算子和行動算子的區別: (不太懂可以看看這個 區別)
Ⅰ.轉換算子返回的是一個新的RDD。行動算子返回的不是RDD,可能是map,list,string等,也可以沒有返回。
Ⅱ.轉換算子相當於邏輯的封裝。行動算子調用sc.runjob執行作業,是對邏輯計算產生結果。
Ⅲ.sortBy算子 既有轉換又有行動的功能,產生一個job,返回一個新的RDD。
①行動算子
行動算子主要是將在數據集上運行計算後的數值返回到驅動程序,從而觸發真正的計算。下面,通過一張表來列舉一些常用行動算子操作的API。
foreach不太會用
② 轉換算子
RDD處理過程中的“轉換”操作主要用於根據已有RDD創建新的RDD,每一次通過Transformation算子計算後都會返回一個新RDD,供給下一個轉換算子使用。下面,通過一張表來列舉一些常用轉換算子操作的API
filter(func) 篩選東西 舉個例子,比如篩選words.txt中的
把hello篩選出來
啥!?竟然說我這個文件不存在,很明顯是存在的,但最後結果是出來的
換成本地進入試試,也成功
在上述代碼中,filter() 輸入的參數 line => line.contains("spark") 是一個匿名函數,其含義是依次取出lines這個rdd中的每一個元素,對於當前取到的元素,把它賦值給匿名函數中的line變量。若line中包含spark單詞,就把這個元素加入到rdd(即 linesWithSpark)中,否則就丟棄該元素。
map(func)
將每個元素傳遞到函數func中,返回的結果是一個新的數據集
以下演示從words.txt 文件中加載數據的方式創建rdd,然後通過map操作將文件中的每一行內容都拆分成一個個的單詞元素,這些單詞組成的集合是一個新的rdd
因爲我有幾個空行,所以顯示了幾個Array("")
上述代碼中,lines.map(line => line.split(" ")) 的含義是依次取出lines這個rdd中的每個元素,對於當前取到的元素,把它賦值給匿名函數中的line變量。由於line是一行文本,一行文本中包含多個單詞,且用空格分隔,通過line.split("")匿名函數,將文本分成一個個的單詞,每一行拆分後的單詞都被封裝到一個數組中,成爲新的rdd(即words)中的一個元素。
flatMap(func)
不知道爲何全拆了
又試了試,發現我拆分的時候少個空格
groupByKey()
groupByKey() 主要用於(key,value)鍵值對的數據集,將具有相同key的value進行分組,會返回一個新的(key,Iterable)形式的數據集。同樣以文件words.txt 爲例,描述如何通過groupByKey算子操作將文件內容中的所有單詞進行分組。
還是全拆了,我把空格刪除再試試
reduceByKey(func)
reduceByKey(func)主要用於(key,value) 鍵值對的數據集,返回的是一個新的(key,value)形式的數據集,該數據集是每個key傳遞給func函數進行聚合運算後得到的結果。
執行words.reduceByKey((a,b) => a + b) 操作,共分爲兩個步驟,分別是先執行reduceByKey操作,將所有key相同的value值合併到一起,生成一個新的鍵值對,比如(“spark”,(1,1,1));然後執行函數func的操作,即使用(a,b)=> a + b函數把(1,1,1)進行聚合求和,得到最終的結果,即(“spark”,3)
三個小案例
案例一 spark實現運營案例
模擬從網頁上獲取日誌,通過日誌分析用戶的pv操作進行了多少次
1.把logs日誌文件建立在linux上
2.進入scala-shell中上傳文件 /export/servers/spark/bin/spark-shell --master local
3.進行區分,整成(pv ,1)
4.進行合併操作用 通過 reduceByKey()
案例二 查看訪問時間
上傳文件
拆分
計數
合併
排序
案例三 獨立訪客
所謂獨立訪客,就是把每個IP給分出來,然後計數
上傳文件
按照空格分割
去重
寫1
相加求和 記得用reduceByKey
下載文件
嘿嘿,結束昨天的任務~