大數據技術之_19_Spark學習_05_Spark GraphX 應用解析小結

========== Spark GraphX 概述 ==========
1、Spark GraphX是什麼?
  (1)Spark GraphX 是 Spark 的一個模塊,主要用於進行以圖爲核心的計算還有分佈式圖的計算。
  (2)GraphX 他的底層計算也是 RDD 計算,它和 RDD 共用一種存儲形態,在展示形態上可以以數據集來表示,也可以圖的形式來表示。

2、Spark GraphX 有哪些抽象?
(1)頂點。
  頂點的表示用 RDD[(VertexId, VD)] 來表示,(VertexId, VD) 這個元組用來具體表示一個頂點,VertexID 表示頂點的 ID,是 Long 類型的別名,VD 是頂點的屬性,是一個類型參數,可以是任何類型。
(2)邊。
  邊的表示用 RDD[Edge[ED]] 來表示,Edge 用來具體表示一個邊,Edge 裏面包含一個 ED 類型參數來設定的屬性,ED 類型中包括 一個源頂點的 ID 和一個目標頂點的 ID。
(3)三元組。
  三元組結構用 RDD[EdgeTriplet[VD, ED]] 來表示,EdgeTriplet[VD, ED] 來表示一個三元組,三元組包含了一個邊、邊的屬性、源頂點 ID、源頂點屬性、目標頂點 ID、目標頂點屬性。VD 和 ED 是類型參數,VD 表示頂點的屬性,ED 表示邊的屬性。
(4)圖。
  圖在 Spark 中用 Graph[VD, ED] 來表示,可以通過頂點和邊來構建。

========== Spark GraphX 圖的構建 ==========
1、對於 Vertex 頂點的構建:
(1)對於 RDD[(VertexId, VD)] 這種版本:

val users: RDD[(VertexId, (String, String))] = sc.parallelize(Array((3L, ("rxin", "student")), (7L, ("jgonzal", "postdoc")),(5L, ("franklin", "prof")), (2L, ("istoica", "prof"))))

(2)對於 VertexRDD[VD] 這種版本:是頂點的構建的優化版本。說白了,就是對上面版本的包裝,包裝中進行了一些優化!

val users1: VertexRDD[(String, String)] = VertexRDD[(String, String)](users)

2、對於 Edge 邊的構建:
(1)對於 RDD[Edge[ED]] 這種版本:

val relationships: RDD[Edge[String]] = sc.parallelize(Array(Edge(3L, 7L, "collab"), Edge(5L, 3L, "advisor"), Edge(2L, 5L, "colleague"), Edge(5L, 7L, "pi")))

(2)對於 EdgeRDD[ED] 這種版本:是邊的構建的優化版本。說白了,就是對上面版本的包裝,包裝中進行了一些優化!

val relationships1: EdgeRDD[String] = EdgeRDD.fromEdges(relationships)

3、對於 Graph 圖的構建:
Graph[VD: ClassTag, ED: ClassTag]
(1)通過 Graph 類的 apply 方法來構建。

val users: RDD[(VertexId, (String, String))] = sc.parallelize(Array((3L, ("rxin", "student")), (7L, ("jgonzal", "postdoc")),(5L, ("franklin", "prof")), (2L, ("istoica", "prof"))))
val relationships: RDD[Edge[String]] = sc.parallelize(Array(Edge(3L, 7L, "collab"), Edge(5L, 3L, "advisor"), Edge(2L, 5L, "colleague"), Edge(5L, 7L, "pi")))
val defaultUser = ("John Doe", "Missing")
val graph = Graph(users, relationships) 

def apply[VD: ClassTag, ED: ClassTag](
    vertices: RDD[(VertexId, VD)],
    edges: RDD[Edge[ED]],
    defaultVertexAttr: VD = null.asInstanceOf[VD],
    edgeStorageLevel: StorageLevel = StorageLevel.MEMORY_ONLY,
    vertexStorageLevel: StorageLevel = StorageLevel.MEMORY_ONLY): Graph[VD, ED]

測試代碼:

scala> val users: RDD[(VertexId, (String, String))] = sc.parallelize(Array((3L, ("rxin", "student")), (7L, ("jgonzal", "postdoc")),(5L, ("franklin", "prof")), (2L, ("istoica", "prof"))))
users: org.apache.spark.rdd.RDD[(org.apache.spark.graphx.VertexId, (String, String))] = ParallelCollectionRDD[0] at parallelize at <console>:26

scala> val relationships: RDD[Edge[String]] = sc.parallelize(Array(Edge(3L, 7L, "collab"), Edge(5L, 3L, "advisor"), Edge(2L, 5L, "colleague"), Edge(5L, 7L, "pi")))
relationships: org.apache.spark.rdd.RDD[org.apache.spark.graphx.Edge[String]] = ParallelCollectionRDD[1] at parallelize at <console>:26

scala> val defaultUser = ("John Doe", "Missing")
defaultUser: (String, String) = (John Doe,Missing)

scala> val graph = Graph(users, relationships)
graph: org.apache.spark.graphx.Graph[(String, String),String] = org.apache.spark.graphx.impl.GraphImpl@4285b1bd

scala> graph.vertices.collect.foreach(println _)
(5,(franklin,prof))                                                             
(2,(istoica,prof))
(3,(rxin,student))
(7,(jgonzal,postdoc))

scala> graph.edges.collect.foreach(println _)
Edge(3,7,collab)
Edge(5,3,advisor)
Edge(2,5,colleague)
Edge(5,7,pi)

(2)通過 Graph 類提供 fromEdges 方法來構建。注意:對於頂點的屬性是使用提供的默認屬性。

val relationships: RDD[Edge[String]] = sc.parallelize(Array(Edge(3L, 7L, "collab"), Edge(5L, 3L, "advisor"), Edge(2L, 5L, "colleague"), Edge(5L, 7L, "pi")))
val defaultUser = ("aaa", "bbb")
val graph2 = Graph.fromEdges(relationships, defaultUser)

def fromEdges[VD: ClassTag, ED: ClassTag](
    edges: RDD[Edge[ED]],
    defaultValue: VD,
    edgeStorageLevel: StorageLevel = StorageLevel.MEMORY_ONLY,
    vertexStorageLevel: StorageLevel = StorageLevel.MEMORY_ONLY): Graph[VD, ED]

測試代碼:

scala> val relationships: RDD[Edge[String]] = sc.parallelize(Array(Edge(3L, 7L, "collab"), Edge(5L, 3L, "advisor"), Edge(2L, 5L, "colleague"), Edge(5L, 7L, "pi")))
relationships: org.apache.spark.rdd.RDD[org.apache.spark.graphx.Edge[String]] = ParallelCollectionRDD[15] at parallelize at <console>:26

scala> val defaultUser = ("aaa", "bbb")
defaultUser: (String, String) = (aaa,bbb)

scala> val graph2 = Graph.fromEdges(relationships, defaultUser)
graph2: org.apache.spark.graphx.Graph[(String, String),String] = org.apache.spark.graphx.impl.GraphImpl@52fb37d7

scala> graph2.vertices.collect.foreach(println _)
(5,(aaa,bbb))
(2,(aaa,bbb))
(3,(aaa,bbb))
(7,(aaa,bbb))

scala> graph2.edges.collect.foreach(println _)
Edge(3,7,collab)
Edge(5,3,advisor)
Edge(2,5,colleague)
Edge(5,7,pi)

(3)通過 Graph 類提供的 fromEdgeTuples 方法來構建。注意:對於頂點的屬性是使用提供的默認屬性,對於邊的屬性是相同邊的數量。

val relationships: RDD[(VertexId, VertexId)] = sc.parallelize(Array((3L, 7L), (5L, 3L), (2L, 5L), (5L, 7L)))
val defaultUser = ("haha", "heihei")
val graph3 = Graph.fromEdgeTuples[(String, String)](relationships, defaultUser)

def fromEdgeTuples[VD: ClassTag](
    rawEdges: RDD[(VertexId, VertexId)],
    defaultValue: VD,
    uniqueEdges: Option[PartitionStrategy] = None,
    edgeStorageLevel: StorageLevel = StorageLevel.MEMORY_ONLY,
    vertexStorageLevel: StorageLevel = StorageLevel.MEMORY_ONLY): Graph[VD, Int]

測試代碼:

scala> val relationships: RDD[(VertexId, VertexId)] = sc.parallelize(Array((3L, 7L), (5L, 3L), (2L, 5L), (5L, 7L)))
relationships: org.apache.spark.rdd.RDD[(org.apache.spark.graphx.VertexId, org.apache.spark.graphx.VertexId)] = ParallelCollectionRDD[26] at parallelize at <console>:26

scala> val defaultUser = ("haha", "heihei")
defaultUser: (String, String) = (haha,heihei)

scala> val graph3 = Graph.fromEdgeTuples[(String, String)](relationships, defaultUser)
graph3: org.apache.spark.graphx.Graph[(String, String),Int] = org.apache.spark.graphx.impl.GraphImpl@5cb7311b

scala> graph3.vertices.collect.foreach(println _)
(5,(haha,heihei))
(2,(haha,heihei))
(3,(haha,heihei))
(7,(haha,heihei))

scala> graph3.edges.collect.foreach(println _)
Edge(3,7,1)     第三個元素“1”表示的是相同邊的數量
Edge(5,3,1)
Edge(2,5,1)
Edge(5,7,1)

========== Spark GraphX 圖的基本信息轉換 ==========
1、graph.numEdges 返回當前圖的邊的數量
2、graph.numVertices 返回當前圖的頂點的數量
3、graph.inDegrees 返回當前圖每個頂點入度的數量,返回類型爲 VertexRDD[Int]
4、graph.outDegrees 返回當前圖每個頂點出度的數量,返回的類型爲 VertexRDD[Int]
5、graph.degrees 返回當前圖每個頂點入度和出度的和,返回的類型爲 VertexRDD[Int]

========== Spark GraphX 圖的轉換操作 ==========
1、def mapVertices[VD2: ClassTag](map: (VertexId, VD) => VD2) (implicit eq: VD =:= VD2 = null): Graph[VD2, ED]
  對當前圖每一個頂點應用提供的 map 函數來修改頂點的屬性,返回一個新的圖。
2、def mapEdges[ED2: ClassTag](map: Edge[ED] => ED2): Graph[VD, ED2]
  對當前圖每一條邊應用提供的 map 函數來修改邊的屬性,返回一個新圖。
3、def mapTriplets[ED2: ClassTag](map: EdgeTriplet[VD, ED] => ED2): Graph[VD, ED2]
  對當前圖每一個三元組應用提供的 map 函數來修改邊的屬性,返回一個新圖。

========== Spark GraphX 圖的結構操作 ==========
1、def reverse: Graph[VD, ED]
  該操作反轉一個圖,產生一個新圖,新圖中的每條邊的方向和原圖每條邊的方向相反。
2、def subgraph(epred: EdgeTriplet[VD, ED] => Boolean = (x => true), vpred: (VertexId, VD) => Boolean = ((v, d) => true)) : Graph[VD, ED]
  該操作返回一個當前圖的子圖,通過傳入 epred 函數來過濾邊,通過傳入 vpred 函數來過濾頂點,返回滿足 epred 函數值爲 true 的邊和滿足 vpred 函數值爲 true 頂點組成子圖。
3、def mask[VD2: ClassTag, ED2: ClassTag](other: Graph[VD2, ED2]): Graph[VD, ED]
  mask 函數用於求一張圖和 other 這張圖的交集,該交集的判別條件指的是:1、對於頂點,只對比頂點的 ID。2、對於邊,只對比邊的 srcID、dstID,如果 other 和當前圖的交集中的邊、頂點的屬性不一致,那麼 mask 產生的圖默認採用當前圖的屬性。
4、def groupEdges(merge: (ED, ED) => ED): Graph[VD, ED]
  該操作實現將當前圖中的兩條相同邊(邊的 srcID 和 dstID 相同)合併。你需要傳入一個 merge 函數,用於合併這兩邊的屬性返回一個新的屬性。注意:合併兩條邊的前提是,兩條邊在一個分區。

========== Spark GraphX 頂點關聯操作 ==========
1、def joinVertices[U: ClassTag](table: RDD[(VertexId, U)])(mapFunc: (VertexId, VD, U) => VD): Graph[VD, ED]
  該操作通過 mapFunc 函數將 table 中提供的數據更新到相同 VertexId 的屬性裏。
2、def outerJoinVertices[U: ClassTag, VD2: ClassTag](other: RDD[(VertexId, U)])(mapFunc: (VertexId, VD, Option[U]) => VD2)(implicit eq: VD =:= VD2 = null): Graph[VD2, ED]
  該操作和 joinVertices 提供了相同的功能,但是,如果 table 中不存在相對應的頂點(也就是不存 VertexId),這個時候 U 默認是 None。

========== Spark GraphX 聚合操作 ==========
1、def collectNeighbors(edgeDirection: EdgeDirection): VertexRDD[Array[(VertexId, VD)]]
  該操作返回 EdgeDirection 定義的方向中相鄰頂點的 ID 和屬性的集合。
2、def collectNeighborIds(edgeDirection: EdgeDirection): VertexRDD[Array[VertexId]]
  改操作返回 EdgeDirection 定義的方向中相鄰頂點的 ID 的集合。
3、def aggregateMessages[A: ClassTag](sendMsg: EdgeContext[VD, ED, A] => Unit,mergeMsg: (A, A) => A,tripletFields: TripletFields = TripletFields.All): VertexRDD[A]
  該函數用於聚合發送到頂點的信息,A 是發送的信息的類型,sendMsg 是每一條邊都會自動觸發,到底有沒有消息能夠發送到頂點,使用 EdgeContext 裏面的 sendToSrc和sendToDst 來實現。mergeMsg
是每一個頂點都會在接受到所有消息之後調用,主要用於所有接收到的消息的聚合。然後整個函數返回消息的頂點集合 VertexRDD[A]。

我的GitHub地址:https://github.com/heizemingjun
我的博客園地址:https://www.cnblogs.com/chenmingjun
我的CSDN地址:https://blog.csdn.net/u012990179
我的螞蟻筆記博客地址:https://blog.leanote.com/chenmingjun
Copyright ©2018~2019 黑澤君
【轉載文章務必保留出處和署名,謝謝!】

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