Spark【案例】實現黑名單實時過濾

黑名單實時過濾

一、實驗介紹

1.1 實驗內容

本節課主要講解 Spark 的 RDD 操作,讓您對 Spark 算子的特性快速瞭解。通過演示案例實時黑名單過濾,讓您切身體會到 RDD 的強大功能,然後學以致用。

1.2 先學課程

Spark 系列課程

1.3 實驗知識點

  • nc
  • SparkStreaming
  • Spark RDD

1.4 實驗環境

  • spark-2.1.0-bin-hadoop2.6

  • Xfce 終端

1.5 適合人羣

本課程屬於中級難度級別,適合具有 Spark 基礎的用戶,如果對 Scala 熟悉 ,能夠更好的上手本課程。

二、彈性分佈式數據集(RDD)

提到 Spark Transformation,不得不說 Spark RDD,那麼 RDD 是什麼?

彈性分佈式數據集(RDD)是 Spark 框架中的核心概念。它是由數據組成的不可變分佈式集合,其主要進行兩個操作:transformation 和 action。Spark 將數據存儲在不同分區上的 RDD 之中,RDD 可以幫助重新安排計算並優化數據處理過程,此外,它還具有容錯性,因爲 RDD 知道如何重新創建和重新計算數據集。Transformation 是類似在 RDD上 做 filter()、map()或 union() 以生成另一個 RDD 的操作,而 action 則是 count()、first()、take(n)、collect() 等觸發一個計算操作。Transformations 一般都是 lazy 的,直到 action 執行後纔會被執行。Spark Master/Driver 會保存 RDD 上的 Transformations。這樣一來,如果某個 RDD 丟失,它可以快速和便捷地轉換到集羣中存活的主機上。這也就是 RDD 的彈性所在。

RDD 支持兩種類型的操作:

  • 變換(Transformation)變換的返回值是一個新的 RDD 集合,而不是單個值。調用一個變換方法,不會有任何求值計算,它只獲取一個 RDD 作爲參數,然後返回一個新的 RDD。變換函數包括:map,filter,flatMap,groupByKey,reduceByKey,aggregateByKey,pipe 和 coalesce。
  • 行動(Action)行動操作計算並返回一個新的值。當在一個 RDD 對象上調用行動函數時,會在這一時刻計算全部的數據處理查詢並返回結果值。行動操作包括:reduce,collect,count,first,take,countByKey 以及 foreach。

2.1 transformation 操作

  • map(func): 對調用 map 的 RDD 數據集中的每個 element 都使用 func,然後返回一個新的 RDD,這個返回的數據集是分佈式的數據集。
  • filter(func): 對調用 filter 的 RDD 數據集中的每個元素都使用 func,然後返回一個包含使 func 爲 true 的元素構成的 RDD。
  • flatMap(func): 和 map 差不多,但是 flatMap 生成的是多個結果。
  • mapPartitions(func): 和 map 很像,但是 map 是每個 element,而 mapPartitions 是每個 partition。
  • mapPartitionsWithSplit(func): 和 mapPartitions 很像,但是 func 作用的是其中一個 split 上,所以 func 中應該有 index。
  • sample(withReplacement,faction,seed): 抽樣。
  • union(otherDataset): 返回一個新的 dataset,包含源 dataset 和給定 dataset 的元素的集合。
  • distinct([numTasks]): 返回一個新的 dataset,這個 dataset 含有的是源 dataset 中的 distinct 的 element。
  • join(otherDataset,[numTasks]): 當有兩個 KV 的 dataset(K,V)和(K,W),返回的是(K,(V,W))的 dataset,numTasks 爲併發的任務數。
  • cogroup(otherDataset,[numTasks]): 當有兩個 KV 的 dataset(K,V)和(K,W),返回的是(K,Seq[V],Seq[W])的 dataset,numTasks 爲併發的任務數。
  • cartesian(otherDataset): 笛卡爾積簡單說就是 m*n。
  • groupByKey(numTasks): 返回(K,Seq[V]),也就是 hadoop 中 reduce 函數接受的 key-valuelist。
  • reduceByKey(func,[numTasks]): 就是用一個給定的 reduce func再作用在groupByKey產生的(K,Seq[V]),比如求和,求平均數。
  • sortByKey([ascending],[numTasks]): 按照 key 來進行排序,是升序還是降序,ascending 是 boolean 類型。
  • leftOuterJoin: leftOuterJoin 類似於 SQL 中的左外關聯 left outer join,返回結果以前面的 RDD 爲主,關聯不上的記錄爲空。只能用於兩個 RDD 之間的關聯,如果要多個 RDD 關聯,多關聯幾次即可。

2.2 action 操作

  • count(): 返回的是 dataset 中的 element 的個數。
  • first(): 返回的是 dataset 中的第一個元素。
  • take(n): 返回前 n 個 elements,這個是driver program 返回的。
  • takeSample(withReplacement,num,seed): 抽樣返回一個 dataset 中的 num 個元素,隨機種子 seed。
  • reduce(func): 說白了就是聚集,但是傳入的函數是兩個參數輸入返回一個值,這個函數必須是滿足交換律和結合律的。
  • collect(): 一般在 filter 或者足夠小的結果的時候,再用 collect 封裝返回一個數組。
  • saveAsTextFile(path): 把 dataset 寫到一個 text file 中,或者 hdfs,或者 hdfs 支持的文件系統中,spark 把每條記錄都轉換爲一行記錄,然後寫到 file 中。
  • saveAsSequenceFile(path): 只能用在 key-value 對上,然後生成 SequenceFile 寫到本地或者 hadoop 文件系統。
  • countByKey(): 返回的是 key 對應的個數的一個 map,作用於一個 RDD。
  • foreach(func): 對 dataset 中的每個元素都使用 func。

最新的 RDD Operations,請參考: RDD Operations

三、實驗案例之實時黑名單過濾

3.1 案例描述:

在一些企業中,比如小額貸款公司,需要做好風控,對那些信譽不好的用戶,我們需要設置黑名單,只要是黑名單中的用戶,我們就給過濾掉,禁止提供貸款服務。既然是實時,必然用到 SparkStreaming,這裏採用 socketTextStream,結合 nc 命令使用。由於是實驗,不方面提供真實數據,這裏一再簡化,可以簡單模擬一份數據,進行測試,原理是相同的。

注意:模擬的數據字段格式爲(id user),例如: 00001 張三。

3.2 實驗步驟:

1). 雙擊打開桌面 Xfce 終端,首先使用 nc 啓動一個監聽端口8888。

由於我們要使用 socketTextStream傳入一個端口及對應的主機名,不先啓動端口會報錯。

nc -lk 8888

此處輸入圖片的描述

2). 再次雙擊打開桌面 Xfce 終端,啓動 spark-shell。

spark-shell

此處輸入圖片的描述

使用 import 導入依賴。

import org.apache.spark.SparkConf
import org.apache.spark.streaming.StreamingContext
import org.apache.spark.streaming.Seconds

此處輸入圖片的描述

注意:如果是 spark-shell,那麼在進入 spark-shell 的時候,spark-shell 自動創建了一個 SparkContext 爲sc,那麼創建 StreamingContext 只需要用 sc 來 new 就可以了,這樣就不會出現多個sc 的衝突問題,否則會報錯。

創建StreamingContext,設置每一秒刷新一次。

val ssc = new StreamingContext(sc, Seconds(2))

設置需要過濾的黑名單,這裏設置兩個名字,您也可設置多個。

val bl = Array(("Jim", true),("hack", true))

設置並行度,這裏指定爲3。

val blRdd = ssc.sparkContext.parallelize(bl, 3)

此處輸入圖片的描述

設置主機名,端口號。

val st = ssc.socketTextStream("localhost", 8888)

對輸入數據進行轉換,(id, user) => (user, id user) ,以便對每個批次RDD,與之前定義好的黑名單進行leftOuterJoin操作。

val users = st.map { l => (l.split(" ")(1),l) }

此處輸入圖片的描述

調用左外連接操作leftOuterJoin,進行黑名單匹配,過濾掉。



val validRddDS = users.transform(ld => {
      val ljoinRdd = ld.leftOuterJoin(blRdd)
      val fRdd = ljoinRdd.filter(tuple => {
        if(tuple._2._2.getOrElse(false)) {  
          false
        } else {
          true
        }
      })
      val validRdd = fRdd.map(tuple => tuple._2._1) 
      validRdd
    })

此處輸入圖片的描述

#打印白名單
validRddDS.print()
#執行    
ssc.start()
#等待完成
ssc.awaitTermination()

此刻,你會看到每隔一秒不斷刷新。

此處輸入圖片的描述

接下來,回到第一次打開的 Xfce 終端,即監聽 8888 端口。

輸入以下內容:

0001 marry
0003 hack
0002 tom

此處輸入圖片的描述

同理繼續輸入一下內容:

0004 Jim
0005 John
0006 shiro

此處輸入圖片的描述

經過兩次的輸入,發現對黑名單裏的數據都過濾掉,實驗完畢。由於設置的刷新間隔太短您可能,看得不是很清楚,可以將間隔設置大一點,方便觀察。

四、總結

由於篇幅的原因,本節課主要介紹了Spark 的算子操作,包括lazyaction兩種,然後基於一個小案例進行加深學習,涉及到 SparkStreaming 的一些操作。更多的 SparkRDD 操作請參考:Spark 官網

五、參考閱讀

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