GraphX 图数据建模和存储

简介:

背景

简单分析一下GraphX是怎么为图数据建模和存储的。

入口

可以看GraphLoader的函数,

def edgeListFile(
      sc: SparkContext,
      path: String,
      canonicalOrientation: Boolean = false,
      numEdgePartitions: Int = -1,
      edgeStorageLevel: StorageLevel = StorageLevel.MEMORY_ONLY,
      vertexStorageLevel: StorageLevel = StorageLevel.MEMORY_ONLY)
    : Graph[Int, Int]
  1. path可以是本地路径(文件或文件夹),也可以是hdfs路径,本质上是使用sc.textFile来生成HadoopRDD的,numEdgePartitions是分区数。
  2. Graph的存储是分EdgeRDD和VertexRDD两块,可以分别设置StorageLevel。默认是内存。
  3. 这个函数接受边文件,即’1 2’, ‘4 1’这样的点到点的数据对组成的文件。把这份文件按分区数和存储level转化成一个可以操作的图。

流程

  1. sc.textFile读文件,生成原始的RDD
  2. 每个分区(的计算节点)把每条记录放进PrimitiveVector里,这个结构是spark里为primitive数据优化的存储结构。
  3. PrimitiveVector里的数据一条条取出,转化成EdgePartition,即EdgeRDD的分区实现。这个过程中生成了面向列存的结构:src点的array,dst点的array,edge的属性array,以及两个正反向map(用于对应点的local id和global id)。
  4. EdgeRDD 做一次count触发这次边建模任务,真正persist起来。
  5. EdgePartition去生成一个RoutingTablePartition,里面是vertexId到partitionId的对应关系,借助RoutingTablePartition生成VertexRDD
  6. EdgeRDDVertexRDD生成Graph。前者维护了边的属性、边两头顶点的属性、两头顶点各自的global vertexID、两头顶点各自的local Id(在一个edge分区里的array index)、用于寻址array的正反向map。后者维护了点存在于哪个边的分区上的Map。

以下是代码,比较清晰地展现了内部存储结构。

private[graphx]
class EdgePartition[
    @specialized(Char, Int, Boolean, Byte, Long, Float, Double) ED: ClassTag, VD: ClassTag](
    localSrcIds: Array[Int],
    localDstIds: Array[Int],
    data: Array[ED],
    index: GraphXPrimitiveKeyOpenHashMap[VertexId, Int],
    global2local: GraphXPrimitiveKeyOpenHashMap[VertexId, Int],
    local2global: Array[VertexId],
    vertexAttrs: Array[VD],
    activeSet: Option[VertexSet])
  extends Serializable {
/**
 * Stores the locations of edge-partition join sites for each vertex attribute in a particular
 * vertex partition. This provides routing information for shipping vertex attributes to edge
 * partitions.
 */
private[graphx]
class RoutingTablePartition(
    private val routingTable: Array[(Array[VertexId], BitSet, BitSet)]) extends Serializable {

细节

分区摆放

EdgeRDD的分区怎么切分的呢?因为数据是根据HadoopRDD从文件里根据offset扫出来的。可以理解为对边数据的切分是没有任何处理的,因为文件也没有特殊排列过,所以切分成多少个分区应该就是随机的。

VertexRDD的分区怎么切分的呢?EdgeRDD生成的vertexIdToPartitionId这份RDD数据是RDD[VertexId, Int]型,它根据hash分区规则,分成和EdgeRDD分区数一样大。所以VertexRDD的分区数和Edge一样,分区规则是Long取hash。

所以我可以想象的计算过程是:

对点操作的时候,首先对vertexId(是个Long)进行hash,找到对应分区的位置,在这个分区上,如果是内存存储的VertexRDD,那很快可以查到它的边所在的几个Edge分区的所在位置,然后把计算分到这几个Edge所在的分区上去计算。
第一步根据点hash后找边分区位置的过程就类似一次建好索引的查询。

配官方图方面理解:
这里写图片描述

高效数据结构

对原生类型的存储和读写有比较好的数据结构支持,典型的是EdgePartition里使用的map:

/**
 * A fast hash map implementation for primitive, non-null keys. This hash map supports
 * insertions and updates, but not deletions. This map is about an order of magnitude
 * faster than java.util.HashMap, while using much less space overhead.
 *
 * Under the hood, it uses our OpenHashSet implementation.
 */
private[graphx]
class GraphXPrimitiveKeyOpenHashMap[@specialized(Long, Int) K: ClassTag,
                              @specialized(Long, Int, Double) V: ClassTag](

以及之前提到的vector

/**
 * An append-only, non-threadsafe, array-backed vector that is optimized for primitive types.
 */
private[spark]
class PrimitiveVector[@specialized(Long, Int, Double) V: ClassTag](initialSize: Int = 64) {
  private var _numElements = 0
  private var _array: Array[V] = _

全文完 :)

目录
相关文章
|
机器学习/深度学习 搜索推荐 算法
多任务学习之mmoe理论详解与实践
多任务学习之mmoe理论详解与实践
多任务学习之mmoe理论详解与实践
|
机器学习/深度学习 人工智能 安全
千帆大模型平台再升级:接入大模型最多、Prompt模板最全面
千帆大模型平台再升级:接入大模型最多、Prompt模板最全面
609 1
|
缓存 Java 应用服务中间件
一文带你使用xxl-job定时任务
将调度行为抽象形成“调度中心”公共平台,而平台自身并不承担业务逻辑,“调度中心”负责发起调度请求。 将任务抽象成分散的JobHandler,交由“执行器”统一管理,“执行器”负责接收调度请求并执行对应的JobHandler中业务逻辑。 因此,“调度”和“任务”两部分可以相互解耦,提高系统整体稳定性和扩展性;
4218 0
一文带你使用xxl-job定时任务
|
机器学习/深度学习 数据采集 人工智能
探索机器学习在金融欺诈检测中的应用
【8月更文挑战第30天】 随着金融科技的迅猛发展,机器学习技术在保障交易安全和打击金融欺诈中扮演着越来越重要的角色。本文将深入探讨机器学习模型在识别和预防金融欺诈方面的应用,并分析其优势与面临的挑战。通过对比传统方法,我们突出了机器学习在处理大数据、提高检测速度和精度方面的独特价值。同时,文中还将介绍几种常用的算法和模型,以及它们在实际场景中的运用情况。最后,本文提出了未来发展趋势和需要解决的关键问题。
|
SQL 机器学习/深度学习 分布式计算
MaxCompute产品使用合集之如何定时运行任务A,以及定时运行任务B,并且任务B能够独立于任务A运行
MaxCompute作为一款全面的大数据处理平台,广泛应用于各类大数据分析、数据挖掘、BI及机器学习场景。掌握其核心功能、熟练操作流程、遵循最佳实践,可以帮助用户高效、安全地管理和利用海量数据。以下是一个关于MaxCompute产品使用的合集,涵盖了其核心功能、应用场景、操作流程以及最佳实践等内容。
134 0
在钉钉宜搭中,要实现单选关联选项设置与图文展示的关联
在钉钉宜搭中,要实现单选关联选项设置与图文展示的关联
763 7
|
应用服务中间件 网络安全 nginx
nginx 配置 静态html
nginx 配置 静态html
357 0
|
XML 开发框架 缓存
一文看懂 Spring IoC 核心特性
恰逢最近在部门内部做分享,借着这次机会对 Spring IoC 部分又进行了系统的整理,由于大家专业方向和水平不完全一致,因此更多的是让大家了解 Spring 这门技术,分享的内容也站在了更高的角度,希望达到鸟瞰全貌的目的。
519 0
一文看懂 Spring IoC 核心特性
3D接雨水2(leetcode)——Java实现(又是想上吊的一天)
给你一个 m x n 的矩阵,其中的值均为非负整数,代表二维高度图每个单元的高度,请计算图中形状最多能接多少体积的雨水。以下的内容回答你的疑惑和困难。
3D接雨水2(leetcode)——Java实现(又是想上吊的一天)
|
Dart 开发者
【Flutter】底部导航栏实现 ( BottomNavigationBar 底部导航栏 | BottomNavigationBarItem 导航栏条目 | PageView )(二)
【Flutter】底部导航栏实现 ( BottomNavigationBar 底部导航栏 | BottomNavigationBarItem 导航栏条目 | PageView )(二)
430 0
【Flutter】底部导航栏实现 ( BottomNavigationBar 底部导航栏 | BottomNavigationBarItem 导航栏条目 | PageView )(二)