Spark图计算(一)

GraphX是Spark新的组成部分,主要用于图和图的并行计算。在高层,GraphX扩展了Spark RDD,引入新的图抽象:一个属性依附于点和边的有向多图。为支持图计算,GraphX提供一系列基本运算(例如子图、结合点和聚合消息)并优化了Pregel API的变体。此外,GraphX包含了一组图算法和构建器以简化图分析任务。

首先需要在项目中载入Spark和GraphX:

import org.apache.spark._
import org.apache.spark.graphx._
// To make some of the examples work we will also need RDD
import org.apache.spark.rdd.RDD
如果不使用Spark壳则需要载入SparkContext。

属性图

属性图是一个有向多图,用户自定义对象依附于点和边。一个有向多图是一个有向图,可能具有多个并行边共享同一起点和终点。支持并行边的能力简化了相同边之间多组关系的建模(例如同事和朋友)。每个点使用唯一的64位识别符号作为键(VertexId)。GraphX不对点识别符强制排序。同样的,边有对应的起点和终点的识别符。

有时需要同一个图中的边有不同的属性,这可以通过继承实现。例如将用户和产品建成两分图,我们使用:

class VertexProperty()
case class UserProperty(val name: String) extends VertexProperty
case class ProductProperty(val name: String, val price: Double) extends VertexProperty
// The graph might then have the type:
var graph: Graph[VertexProperty, String] = null

如同RDD,属性图不可更值,分布式、容错。值或图结构的变动通过生成变动的新图实现。注意原图的大部分(未受影响的结构、属性和索引)在新图中重复利用以降低内在功能数据结构成本。使用点分启发式将图分布在不同执行者。如同RDD,每个图的分块可在失败时在不同的机器重建。

逻辑上属性图对应一组有类型的集合(RDDs),为每个点和边编码

class Graph[VD, ED] {
  val vertices: VertexRDD[VD]
  val edges: EdgeRDD[ED]
}

VertexRDD[VD]和EdgeRDD[ED]是RDD[(VertexId, VD)]和RDD[Edge[ED]]的延伸和优化,提供了围绕图计算的额外功能和内部优化。

举例

假设我们想构建一个具有多个合作者的属性图。点的属性包含用户名和职业。我们可以对边标注字符串描述合作者之间的关系:


结果图具有类型签名

val userGraph: Graph[(String, String), String]
从原始文件构建属性图有多种方式,RDDs,甚至合成生成器。可能最基本的方法是使用Graph对象。例如下列代码构建一个RDD的集合:

// Assume the SparkContext has already been constructed
val sc: SparkContext
// Create an RDD for the vertices
val users: RDD[(VertexId, (String, String))] =
  sc.parallelize(Array((3L, ("rxin", "student")), (7L, ("jgonzal", "postdoc")),
                       (5L, ("franklin", "prof")), (2L, ("istoica", "prof"))))
// Create an RDD for edges
val relationships: RDD[Edge[String]] =
  sc.parallelize(Array(Edge(3L, 7L, "collab"),    Edge(5L, 3L, "advisor"),
                       Edge(2L, 5L, "colleague"), Edge(5L, 7L, "pi")))
// Define a default user in case there are relationship with missing user
val defaultUser = ("John Doe", "Missing")
// Build the initial Graph
val graph = Graph(users, relationships, defaultUser)
上述例子中我们使用Edge类。边有srcId和dstId对应起点和终点辨识器。此外Edge有一个attr储存边属性。

我们可以将图分别分解成graph.vertices和graph.edges。

val graph: Graph[(String, String), String] // Constructed from above
// Count all users which are postdocs
graph.vertices.filter { case (id, (name, pos)) => pos == "postdoc" }.count
// Count all the edges where src > dst
graph.edges.filter(e => e.srcId > e.dstId).count
graph.edges.filter { case Edge(src, dst, prop) => src > dst }.count
属性图除了点和边,GraphX还有一个三重图。三重图将点和边的属性逻辑上结合起来生成一个RDD[EdgeTriplet[VD, ED]]包含EdgeTriplet实例。join可用如下SQL表示

SELECT src.id, dst.id, src.attr, e.attr, dst.attr
FROM edges AS e LEFT JOIN vertices AS src, vertices AS dst
ON e.srcId = src.Id AND e.dstId = dst.Id
或图示如下



EdgeTriplet通过加入srcAttr和dstAttr延展Edge类。我们可以使用三重图来生成字符串集合描述用户间的关系。

val graph: Graph[(String, String), String] // Constructed from above
// Use the triplets view to create an RDD of facts.
val facts: RDD[String] =
  graph.triplets.map(triplet =>
    triplet.srcAttr._1 + " is the " + triplet.attr + " of " + triplet.dstAttr._1)
facts.collect.foreach(println(_))





评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值