Spark GraphX Pregel 应用

一、Pregel介绍

Pregel是一种基于BSP模型实现的并行图处理系统。

BSP(Bulk Synchronous Parallel Computing Model,块同步并行计算模型,又称“大同步”模型)计算过程包括一系列全局超步(所谓的超步就是计算中的一次迭代),每个超步主要包括三个组件:

  1. 局部计算:每个参与的处理器都有自身的计算任务。
  2. 通讯:处理器群相互交换数据。
  3. 栅栏同步(Barrier Synchronization):当一个处理器遇到“路障”(或栅栏),会等到其他所有处理器完成它们的计算步骤。

为了解决大型图的分布式计算问题,Pregel搭建了一套可扩展的、有容错机制的平台,该平台提供了一套非常灵活的API,可以描述各种各样的图计算。

Pregel作为分布式图计算的计算框架,主要用于图遍历、最短路径、PageRank计算等等。

  • Pregel计算模型以有向图作为输入
  • 有向图的每个顶点都有一个String类型的顶点ID
  • 每个顶点都有一个可修改的用户自定义值与之关联
  • 每条有向边都和其源顶点关联,并记录了其目标顶点ID
  • 边上有一个可修改的用户自定义值与之关联
  • 在每个超步S中,图中的所有顶点都会并行执行相同的用户自定义函数。
  • 每个顶点可以接收前一个超步(S-1)中发送给它的消息,修改其自身及其出射边的状态,并发送消息给其他顶点,甚至是修改整个图的拓扑结构。
  • 在这种计算模式中,“边。”并不是核心对象,在边上面不会运行相应的计算,只有顶点才会执行用户自定义函数进行相应计算

采用消息传递模型主要基于以下两个原因:

  1. 消息传递具有足够的表达能力,没有必要使用远程读取或共享内存的方式.
  2. 有助于提升系统整体性能.

二、Pregel的计算过程

Pregel的计算过程是由一系列被称为“超步”的迭代组成的。

在每个超步中,每个顶点上面都会并行执行用户自定义的函数,该函数描述了一个顶点V在一个超步S中需要执行的操作。

该函数可以读取前一个超步(S-1)中其他顶点发送给顶点V的消息,执行相应计算后,修改顶点V及其出射边的状态,然后沿着顶点V的出射边发送消息给其他顶点,而且,一个消息可能经过多条边的传递后被发送到任意已知ID的目标顶点上去。

这些消息将会在下一个超步(S+1)中被目标顶点接收,然后像上述过程一样开始下一个超步(S+1)的迭代过程。

在Pregel计算过程中,一个算法什么时候可以结束,是由所有顶点的状态决定的。

在第0个超步,所有顶点处于活跃状态。

当一个顶点不需要继续执行进一步的计算时,就会把自己的状态设置为“停机”,进入非活跃状态。

当一个处于非活跃状态的顶点收到来自其他顶点的消息时,Pregel计算框架必须根据条件判断来决定是否将其显式唤醒进入活跃状态。

当图中所有的顶点都已经标识其自身达到“非活跃(inactive)”状态,并且没有消息在传送的时候,算法就可以停止运行。
 

以上是搬运工... 转载:https://blog.csdn.net/qq_38265137/article/details/80547763

三、Spark Graphx Pregel 应用

package net.ben

import org.apache.spark.graphx.{Edge, EdgeDirection, Graph}
import org.apache.spark.sql.SparkSession

object PregelDemo {
  /**
   * 数字的顶点的编号,并非顶点的值
   * 
   * 1L --\
   * 2L --- 4L -- 6L
   * 3L --/     /
   * 5L -------/
   * 
   * 编号为4L的顶点,它的值是顶点1L,2L,3L的值的和
   * 1L + 2L + 3L = 4L
   * 
   * 编号为6L的顶点,它的值是顶点4L,5L的值的和
   * 4L + 5L = 6L
   */
  def main(args: Array[String]): Unit = {
    val spark = SparkSession.builder().appName("Spark GraphX Pregel Demo").master("local").getOrCreate()
    val sc = spark.sparkContext

    val vertices = sc.parallelize(Array((6L, 0), (4L, 0), (1L, 1000), (2L, 550), (5L, 300), (3L, 300)))
    // 有向图,Edge(src, dst, attr),
    val edges = sc.parallelize(Array(Edge(1L, 4L, 1), Edge(2L, 4L, 1), Edge(3L, 4L, 1), Edge(4L, 6L, 1), Edge(5L, 6L, 1)))

    val graph = Graph(vertices, edges)
    val result = graph.pregel(0, activeDirection = EdgeDirection.Out)(
      (_, vd, msg) => msg + vd, // vertexProgram 用户自定义函数,计算顶点值
      t => Iterator((t.dstId, t.srcAttr)), // sendMsg 用户自定义函数,发送消息给下一超步
      (x, y) => x + y // mergeMsg 用户自定义函数,合并上一超步的消息
    )
    result.vertices.collect().foreach(println)

    spark.stop
  }
}

输出结果:

(4,1850)
(1,1000)
(6,2150)
(3,300)
(5,300)
(2,550)

参考文献:

https://blog.csdn.net/qq_38265137/article/details/80547763

http://spark.apache.org/docs/latest/graphx-programming-guide.html#pregel-api

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值