分布式系统 Note

分布式文件系统 HDFS

  • Hadoop 简介
  • 分布式文件系统 HDFS
    • 基本特征
      • 大规模分布存储能力
      • 高并发访问能力
      • 强大的容错能力
      • 顺序式文件访问
      • 简单的一致性模型:一次写多次读
      • 数据块存储模式:大力度
  • HDFS 上的数据存储
    • NameNode 保存了一些元数据,主要对 DataNode 进行管理;DataNode 具体对数据块进行存储;
    • 数据以块 block 的形式存储,默认大小为 64M,由于是这样的顺序访问方式提到读写的效率;
  • Hadoop 安装,没啥好说的,看厦大林子雨实验室上的教程即可
  • 常用操作命令

MapReduce

  • 大数据处理:分而治之

  • 构建抽象数据模型:Map 和 Reduce,借鉴了函数式设计语言 Lisp

    • map: (k1; v1) ➞ [(k2; v2)]
    • Reduce: (k2; [v2]) ➞ [(k3; v3)]
    • 其中的 [...] 表示 list
    • 一个例子:word count
  • 上升到框架:自动并行化并隐藏底层细节

    • MR 提供了一个统一的计算框架,实现了一些主要功能
      • 任务调度
      • 数据/代码互定位,代码向数据迁移
      • 出错处理
      • 分布式数据存储与文件管理
      • Combiner 和 Partitioner,为了减少数据通信开销,combine 的目的是合并一些中间结果,而 partition 的目的是避免广播而使用一定的策略确保相关数据发送到同一个 reducer 节点
  • MR 的主要涉及思想与特点

    • 向「外」横向拓展,而非向「上」纵向拓展
    • 失效被认为是常态
    • 把处理向数据迁移
    • 顺序处理数据、避免随机访问数据
    • 对应用开发隐藏系统层细节
    • 可拓展性
  • MR 基本工作原理

    • 主从结构,用户和 Master 交互,Master 分配调度 Worker 用来作为 Map 和 Reduce 节点;注意 map 和 reduce 之间需要一个同步等待的时间
  • 各执行阶段

    • 分片split:HDFS 的存储单位的大小固定的 block,而 MR 的处理单位是 split,是一个逻辑概念,理想的大小是一个 block 块;
    • Map 任务的数量等于分片的数量
    • Shuffle 过程
      • Map 端:有一个缓存默认 100M;溢写比例默认 0.8,在溢写的过程中需要分区、排序、合并 combine(👆提到的);map 结束之前会将之前溢写的文件进行归并 merge,整合成一个大的文件;
      • 例如,对于两个键值对 <a, 1>, <a, 1> ,combine 会得到 <a,2> ,而 merge 则只是单纯地把 value 变为 valuelist <a, <1,1>> 。似乎 combine 主要是在内存中完成的,而 merge 则是针对多个溢写文件进行的操作。
      • Reduce 端:Reduce 任务向 JobTracker 请求,领取从不同 Map 机器上的处理结果;先放进缓存,先 merge 后 combine;当然也会有溢写文件,多个溢写文件进行归并成一个大文件。
  • MR 程序执行过程

    • Task 任务是 MR 框架的基本计算单位,是一个逻辑上的概念,存在于 JobTracker 和 TaskTracker 上
  • 作业调度基本过程

    • 每一个作业 Job 被划分成更小粒度的任务 Task,因此 Hadoop 作业调度在选择合适的作业之后还需要从中选择合适的任务,不同的调度器对作业有不同的组织结构,如单队列,多队列,作业池;
  • 算法 #

    • 搜索:可以是仅用到 Map(map-only job)
    • 排序算法:仅需要用到 Partition 部分,保证 \(k_1<k_2\)\(h(k_1)<h(k_2)\)
    • 单词同现矩阵
      • 我们把一篇文档中的单词认为是「同现」的,要求计算所有单词的这样的一个相关关系的矩阵,显然没法直接存下来
      • MR 的思路是,在 Map 阶段对于每一篇文档,每一组词输出 [(w1, w2), 1] 的形式,在 Reduce 阶段汇总即可;
      • 优化:太多的小 key (a,b):1,(a,c):2 等,把这些 pairs 统合成 strips a:{b:1, c:2}
    • 文档倒排索引 Inversed Index
      • 要求对于这些文档中的单词构建一个索引,key 是单词,value 是文档列表;
      • 除了仅仅列出文档名,更为实用的是加入一些属性,有效负载 Payload,例如加入词频属性;这时的 map 输出是 word, [(docid, n)] 的形式;
      • 为了对出现频次进行排序,变为 (word, n), docid 的形式,复合键;
      • 同时也带来了新问题:直接用默认的 Partitioner 可能把同一个词分到不同的 Reducer,因此需要手动配置 Partitioner 把 key (word, docid) 中的 word 抽取出来作为准则
    • K-Means 聚类
      • 这里首次涉及到了迭代的算法,K-Means 的特点在于,对每一个点在每一轮只需要计算其与各个分类中心的距离——也就是说,我们需要的「全局信息」仅仅是各分类中心的位置
      • 为此,维护一个全局信息,保存各分类中心的 id, center, #points (其中属于该类的数据点个数好像在实际迭代中不会用到?不过最终的结果可能是需要的)
      • 在 Map 中计算点所属的类
      • 在 Reduce 中汇总得到类中心

Hbase 数据库

  • 从 BigTable 到 Hbase
  • 概念
    • 数据模型:表……
    • 数据坐标,一个 cell 由四维坐标定位:[行键, 列族, 列限定符, 时间戳]
    • 概念试图和物理视图
    • 面向列的存储
  • Hbase 实现原理
    • 功能组件:库函数(链接到每个客户端)、Master 服务器、Region 服务器
    • Region 的定位:一个列族最终拆分成很多个 Region 进行存储;而在定位的过程中,客户端不和 Master 打交道而直接和 Zookeeper 通信;这样降低了 Master 的负载
      • Zookeeper 记录了 -ROOT- 表的位置
      • -ROOT- 表只能有一个 Region,记录了各个 .META. 表的位置信息
      • .META. 表保存了用户数据表中的 Region 位置信息,可以有多个 Region
    • 这样就变成了「三级寻址」,不过思想也很简单,用 .META. 表存储位置信息,但因为单个的表不够存储,所以另外引入了 -ROOT- 表,从而提高了可以索引的 Region 数量
    • 另外,客户端有缓存机制,记录了已访问的 Region 地址
  • Hbase 运行机制
    • 这里讲了细节的 Region 服务器工作原理,每一个 Region 服务器包括多个 Region,然后每一个 Region 又有多个 Store 进行存储,每个 Store 包括了一个缓存 MemStore 和多个 StoreFile 文件;同时,一个服务器上的多个 Region 共享一个日志文件(预写式日志 Write Ahead Log WAL);更新的数据写入了日志之后才会写入 MenStore
    • 缓存满了之后写成 StoreFile,并在 Hlog 中写入一个标记;StoreFile 文件过多的时候回进行合并,单个 StoreFile 过大又会分裂(一个父 Region 分裂成两个子 Region)
    • 显然,Hlog 文件是用来恢复的,对于失效的服务器,取出 Hlog 文件进行分拆到另外的多个 Region 服务器上,并根据失效服务器上的 Region 文件进行重新的写入
    • 这样听起来似乎很复杂(没有相关的背景知识),但实际上就是一个 Log Structured Merge Trees 存储结构:用 MemStore 缓存加速写入,满了之后刷写成 Store,文件太多的时候进行 Merge,除此之外再加上 WAL 日志。
  • HBase 应用方案
    • 性能优化:利用行键是根据字典序存储这一特性涉及行键;其他的一些具体代码实现
    • 性能监视
    • 在 HBase 上构建 SQL 引擎
      • Hive 整合 Hbase
      • Phoenix
    • 创建 HBase 二级索引

NoSQL

  • SQL,一些问题,新的使用场景,无法满足海量数据、并发访问、高拓展性、高可用等需求

  • NoSQL 理论

    • CAP 理论)一个系统的三种属性:consistency, availability, partition tolerance。只能得其二,而为了 scale out 必须进行 Partition,这意味着需要在可用性和一致性之中进行权衡。这里的 P 是 tolerance of network partition 分区容忍性,是指当网络出现了分区时系统仍可以运行。
    • 一致性
      • 强一致性:ACID - Atomic, Consistent, Isolated, Durable
      • 弱一致性:BASE - Basically Available Soft-state Eventual consistency
        • 基本可用,分布式系统一部分出现问题的时候,其余部分仍然可用,即允许网络分区
        • 软状态(放松一致性),与硬状态对应,是指状态可以有一段时间不同步,具有一定的滞后性
        • 最终一致性,即意味着在经历了较长的一段没有事务之后,网络中的节点之间是一致的(最常见的系统是 DNS 域名系统,有缓存)
    • CA:放弃分区容忍性,传统的关系数据库,拓展性较差
    • CP:放弃可用性,当出现网络分区的情况时,受影响的服务需要等待数据一致性
    • AP:放弃一致性,允许系统返回不一致的数据
  • 对于一个分布式系统来说,记 N 为数据复制的份数,W 为更新数据是需要保证写完成的节点数,R 为读取数据时需要读取的节点数;控制三者的关系,可以实现不同的一致性

    • \(W+R>N\) 强一致性
    • \(W+R\le N\) 弱一致性,如 \(N=2, W=R=1\) 这时无法保障
  • NoSQL 数据库与关系数据库的比较

    • 从数据规模;数据库模式;查询效率;一致性;数据完整性;扩展性;可用性等角度
  • 分类

    • 键值数据库:如 Redis, Riak, SimpleDB
    • 列族数据库:如 BigTable, Hbase, Cassandra HadoopDB
    • 文档数据库:如 MongoDB, CouchDB
    • 图数据库:如 Neo4J, OrientDB
  • 后面介绍了一点 MongoDB

Hadoop 数据仓库

  • SQL 概述
    • 数据库、基本表、视图、索引
    • 基本命令
  • 数据仓库 Data Warehouse DW
    • Subject Oriented, 面向主题的
    • Integrated, 多种数据类型
    • Non-Volatile, 不允许修改数据
    • Time Variant, 记录同一个字段不同时间的 value
    • OLAP Online analytical processing, 分析数据
    • 层次化,不同粒度 Granularity 的数据
  • Hive
    • 系统架构
      • 用户接口模块:CLI, HWI, JDBC, Trift Server
      • 驱动模块 Driver:编译器、优化器、执行器
      • 元数据存储模块 Metastore,是一个独立的关系数据库,Derby 或者 MySQL
    • 底层依赖于 HDFS 和 MR;因此和传统 DB 不同的,例如仅支持批量更新;不支持数据更新;延时高
    • Hive 工作原理
      • 介绍了把 HiveQL 语言转化为 MR 作业:join, group by, 等
    • 高可用 High Availability HA
      • 由多个 Hive 实例组成,纳入到一个资源池中,由 HAProxy 提供一个统一的对外接口
    • 总结一下优缺点
      • 分布式数据仓库,支持大数据集查询;支持类似 SQL 的查询语言 HiveQL;有类似关系数据库的表结构和概念;多种格式数据的结构化管理;
      • OLAP 应用;一些子查询和联合等 SQL 操作性能不佳;总体上采用 MR,适合批处理,反应速度不佳
  • Impala
    • 并行数据库架构类型
      • Shared memory
      • shared disk
      • shared nothing,每个节点由处理器、内存和磁盘组成,通过网络和其他 Node 的处理器通信
      • hierachical
    • 系统架构
      • Impalad
        • 负责协调客户端提交的查询的执行
        • 与 HDFS 的 DataNode 运行在同一个节点上(每个 DataNode 上都有)
        • 可以针对 HDFS 或者是 HBase 的数据进行操作
      • State Store
        • 创建一个 statestored 进程
        • 负责收集分布在集群中各个 Impalad 进程的资源信息,用于查询调度
      • CLI
        • 给用户提供查询使用的命令行工具;提供 Hue, JDBC, ODBC 使用接口
    • 具体的查询执行过程挺复杂的,略去
  • Hive 和 Impala 比较
    • 不同点
      • Hive 适合长时间批处理查询,Impala 适合实时交互的 SQL 查询
      • Hive 依赖于 MR 计算框架,而 Impala 把执行计划表现为一棵完整的执行计划树,直接分发执行计划到各个 Impalad 执行查询
      • Hive 执行过程中若内存不够可以借助外存,而 Impala 则不会,因此有所限制
    • 相同点
      • 使用相同的存储数据池,都支持把数据存储与 HDFS 和 HBase 中
      • 使用相同的元数据
      • 对于 SQL 的解释处理比较相似,都是通过语法分析生成执行计划
  • Hive 部署

Spark

  • 简介
    • Hadoop 的一些缺点:表达能力有限;磁盘 IO 开销大;延迟高
    • 基于内存的 Spark 对于迭代运算的效率更高;基于 DAG 的任务调度执行机制要优于 MR 的迭代执行机制
    • 实际应用中的三种需求:复杂的批量数据处理、基于历史数据的交互式查询、基于实时数据流的数据处理,对于时间跨度有不同的需求,原本需要 MR、Impala、Storm 结合处理,显然会带来不便;而 Spark 所提供的生态可以提供一站式的方案(Spark、Spark SQL、Spark Streaming)
  • Spark 运行架构
    • RDD 的思想
    • 一个 Application 由一个 Driver 和多个 Job 组成;一个 Job 由多个 Stage 构成;一个 Stage 又由多个没有 Shuffle 关系的 Task 组成,Task 是运行在 Executor 的基本单元;
    • 当执行一个 Application 的时候,Driver 向集群管理器申请资源启动 Executor,然后在 Executor 上执行 Task,结束后将结果返回给 Driver 或是直接写到 HDFS/数据库中。
  • 运行基本流程
    • 具体的流程中,由 Driver 构建一个 SparkContext,进行资源的申请、任务的分配和监控
    • SC 和任务管理器交互,分配 Executor
    • SC 根据 RDD 的依赖关系构建 DAG 图,由 DAGScheduler 解析成 Stage,把这些 Stage/Taskset 交给 TaskScheduler(底层的调度器);Executor 向 SC 申请 Task,TaskScheduler 将 Task 分配给 Executor 运行
    • Executor 运行代码,将执行结果反馈给 TaskScheduler 和 DAGScheduler,执行结束后写入数据
    • 听起来好像很复杂,涉及到的概念比较多,看了后面的 RDD 原理之后会更清楚,主要是由 Driver 构建了一个 SC 进行管理;因为用到的 RDD 和 DAG 任务管理机制,所以在 Driver 中有不同的组件来操作;Application 是总体的抽象包括了 Driver 和几个Job(相对独立/完整,可以理解成 RDD 中的 action)
  • RDD 运行原理
    • RDD 提供了「一种高度受限的共享内存模型」,即 RDD 是只读的记录分区的集合。
    • RDD 提供了分类 action 和 transformation 的操作,两者的区别在于action 输入之后会立即执行而 transformation 遵循惰性机制;这一系列的操作构成 DAG, 称为血缘关系 Lineage,即 DAG 拓扑排序的结果。
    • 在此基础上有一些优势,例如 RDD 本身就有高效的容错机制;存放在内存中避免 IO;存放的数据可以是 Java 对象从而避免了序列化和反序列化。
    • 关于 RDD 中 Stage 的划分,整个流程我们可以转化为一个 DAG 图,通过这些 RDD 中的分区之间的依赖关系进行划分 Stage;具体来说,对 DAG 进行反向解析,遇到宽依赖就断开生成新的 Stage,遇到窄依赖则加入到这个 Stage 中,所谓的宽依赖,就是存在一个父 RDD 的一个分区对应一个子 RDD 的多个分区。Stage 可以看成一个 Taskset,分配到具体的 Executor 上去运行。
  • RDD 操作
    • Transformation
    • Action
    • Persistence
  • 例子:基于 PySpark 实现的 word count、矩阵乘法
  • 最后讲了一点 Hive on Spark 和 Spark SQL,以及两者之间的区别。后者相对不依赖 Hive 环境。
  • 例子:K-Means 聚类、PageRank
    • K-Means 的话,和上面讲 MR 时候的思路是一样的,我们关注的是 K 个中心的位置,而不变量是所有点的位置;在每一轮迭代中,用 map 找到最近的那个中心点,reduce 进行汇总,取平均以更新各中心点的位置即可;这里用了一个 Auxiliary 函数以计算一个点最近的那个中心;
    • PageRank,首先需要设计数据结构,这里用了 links 保留链接/网络结构,用 ranks 单独记录各 url 的 rank;主循环的时候将两者结合起来,flatMap 阶段分发某个 url 对其指向链接的权重,reduce 阶段加和汇总并引入随机浏览;
    • 这里使用 Spark SQL 来实现的,但感觉和 Spark 没啥区别?至少是代码结构上,可能 from pyspark.sql import SparkSession 和之前直接从 from pyspark import SparkContext 是类似的吧,下面的代码也可以用 RDD 模型
  • 对于关系数据,举了 Spark SQL 的例子
    • 没有实际试过,不过和 SQL 很像,感觉主要的和👆的两个例子不同之处在于用了 sc.createDataFrame 等相关的函数来生成结构化的数据
  • 最后提了 RDD, DataFeame, DataSet

Streaming Computing 流计算

  • 流计算概述

    • 静态数据和流数据
    • 对应了批量计算和实时计算两种计算模式
  • 流计算框架

    • 商业级:IBM InfoSphere Streams
    • 开源计算框架:Twitter Storm, Yahho! S4
    • 公司自研发:Facebook Puma, Baidu Dstream
  • 流程

    • 数据实时采集
    • 数据实时计算
    • 数据查询服务(实时数据而非传统数据处理中的预先存储好的静态数据)
  • Storm

    • Storm 设计思想
      • Streams:将数据流描述成一个无限的 Tuple 序列,每个 tuple 都是一个键值对的 Map;由于各组件之间传递的 tuple 的字段名称都是事先定义的,因此实际上仅需要传 Value List 即可
      • Spout:抽象的「水龙头」
      • Bolt:用于 Stream 的状态转换,处理 tuples,创建新的 Streams
      • Topology:个 Spout 和 Bolt 组件抽象出来的网络,Topology 中的每一个组件并行运行
      • Stream Groupings:用于告知 Topology 如何在两个组件之间进行 Tuple 的传送
    • Storm 框架设计
      • 应用名称:总体上来看,Hadoop 运行的是 MR Job,而 Storm 上运行的是 Topology;

        系统角色:JobTracker 和 TaskTracker 分别对应 Storm 中的 Nimbus 和 Superviser(运行在 Worker 上);

        组件接口:Map/Reduce 对应 Spout/Bolt;

        用 Zookeeper 作为分布式协调组件,负责 Nimbus 和 Supervisor 之间的协调工作。

      • 在 Worker 节点上,运行着若干个 Worker 进程

        每个 Worker 进程内部有若干 Executor 线程(但默认下 Executor 和 Task 的数量一样,即每个 Executor 上运行一个 Task);

        实际的数据处理由 Task 完成,每个 Task 对应了 Topology 中的 Spout/Bolt。

  • 例子:用 Storm 实现 word count

  • Spark Streaming

    • SS 的基本原理是对实时输入的数据流以时间片为单位进行划分,以类似批处理的方式进行处理;主要把数据流抽象成 DStream (Discreted Stream);当然这也导致了其无法实现真正毫秒级的流计算

图处理 Graph Processing

  • 定义

    • Vertex, Edge
    • Eccentricity 一个顶点距离其他顶点的距离的最大值;在此基础上定义了 Radius 为图中任意顶点的 eccentricity 的最小值;Diameter 是图中任意顶点的 eccentricity 的最大值,即图中任意两点之间的距离的最大值。
  • Graph Queries

    • 对于一张图 G,输入一个子图 Q 进行 query
    • 分为 Subgraph isomorphism,需要节点/边之间的一一对应关系,双射,可理解成等价关系。NP-complete
    • Graph simulation,定义是要求一个二元关系 S,满足对任意 \((u,v)\in S\),在 Q 上的边 \((u,u')\) 映射到 G 上的 \((v,v')\),使得 \((u', v')\in S\)
    • 子图查询是比较严谨的,而 simulation 则相对宽松一些,背景例如,需要从一个社交网络中找到犯罪团体,显然对于 pattern graph 不可能找到完全一致的子图同构,这是就需要 simulation。
  • 回顾了一下关系数据库:schema,关系查询中的 Projection, Selection, Join, Union, Set difference, Group by and Aggregate

  • 以及 XML 查询。SML 文档可以建模为一个 node-labeled ordered tree;XML 上的查询可以用 XPATH, XSLT, XQuary 等

  • 提到的图查询的难点:1. 半结构化,没有 schema 或者 constraint,没有统一的查询语言;2. 图计算的很多操作复杂性高;2. 真实的图非常大,甚至 Polynomial/Linear 的算法都不可行

  • Graph systems

    • Graph query engines: Giraph (Pregel, Google), GraphLab, Neo4j, GraphX
    • Key-value stores
    • RDF triple stores
  • Reachability queries

    • 仅需要查询两点是否可达,采用 BFS,复杂度是 \(O(|V|+|E|)\) 的时间和空间
    • 另一种方案是 2-hop cover,即对于每一个 v 维护 \(2hop(v)=(L_{in}(v), L_{out}(v))\) ,前者是所有能到 v 的节点,后者是所有 v 能到达的顶点,s 可到达 t 等价于 \(L_{out}(s)\cap L_{in}(t)\ne \varnothing\) ;测试来看时间复杂度要比 BFS 好些
  • Distance queries

    • 对于一个点 s,找到其与 G 中其他任意点的距离,如用在运输网络中
    • 经典的算法是 Dijkstra,就是一个 BFS,每次用最短的那个顶点(距离已经确定了)去更新其余的顶点
    • MR 实现:来看对于一个顶点需要哪些信息,显然是其入度邻居对它的更新;另外需要注意的是 MR 过程中需要维护图的结构。因此,在 Map 阶段,首先原样输出 (nid m, node M) 其中包含了邻居列表(结构信息),然后利用自己的距离去更新其邻居节点;在 Reduce 阶段,对于每一个 nid m,接收顶点 node M,并从其入度邻居的中找到最小的那一个看是否能更新,重新整理成节点 (nid m, node M) 的形式输出。Termination 的话,可以设置一个 flag 检测是否发生了更新,这需要一个 non-MapReduce driver 来控制。
    • 效率的话,相较于 Dijkstra 显然很低:1. 每一轮迭代中对于每一个节点都进行了操作,分发给所有的出度邻居;2. 不同计算节点之间消息传输的成本
  • MatchIng by subgraph isomorphism

    • VF2,算法很直观:是 recursion, refinment 的,每次迭代维护一个集合 P 记录了可能的同构,在迭代中把点加入进来形成 \(S(P)\),这与这些新的可能的同构进行 feasibility check
    • 关键在于可行性检测
      • their predecessors are already mapped and included in P
      • their successors can possibly be mapped
      • Certain conditions on cardinalities of predecessors and successors to ensure correctness and expandability
    • MR 版本,一个极为蠢的算法,对每一个顶点挖出其 d-hop 的子图,d 为 Q 的半径,在每一个这样的子图上进行查询;仅仅是概念上的,效率太低了。
  • MR 算法的局限性,其本身不支持迭代式的算法

    • 中间结果的传递是 all to all 的;Reduce 需要等待所有的 Map 结束之后才能开始;IO 消耗……
  • BSP Bulk Sychronous Parallel Model

    • 由一系列的超步 superstep 组成;每一个超步中,计算单元实现内部计算;超步之间实现消息传递 MP 和同步栅 sychronization barriar
    • 具体到图计算上,这里的计算单元就是图中的每一个顶点,在一个超步中:1. 接受上一个超步其他顶点的 message;2. 本地计算;3. 传递 message 给下一步的其他顶点。超步中所有的顶点 parallel 计算。
  • Pregel

    • 算法如何结束?类似于一个 flag,不过这里的表述的每个顶点 vote to halt,当所有顶点都 inactive 的时候结束
    • 总而言之,是 vertix centric computation
    • 例子:maximum value,这里向每个邻居节点传输该顶点的大小;每个顶点选最大的最后新的值;若出现了更新则调整状态为 active。
    • 例子:PageRank,更加直观了,这里伪代码直接迭代了 30 此就结束了
    • 例子:Dijkstra,也是直观的
  • 其他的一些性质

    • Combiner:可以对于一个超步中的传递给一个顶点的所有消息进行 combine,例如 Dijkstra 中取最小值
    • Aggregation:每个顶点可以传递信息给 aggregator,其他的所有顶点在下一个超步可以读取;相当于引入了一个全局变量,restricted global communication
    • Topology mutation:支持图的结构变化
  • Pregel 框架

    • 还是主从结构
    • 最好的分配顶点的方式,自然是要求 Worker 之间的信息交互最少,也即 Sparsest Cut Problem 问题(最小化切割经过的边数),不过是 NP-harp 的。
  • 然后,从根本上来说,Pregel 的超步等策略,其实还是类似于 MR;只不过它对于每一个顶点建立计算单元,根据图的网络结构进行消息传递,是专门针对的图计算的一种计算框架;也就是说,Pregel 能做的 MR 也基本可以实现,只不过效率稍微低一点,而 MR 不适合做的 Pregel 也不适合做,例如之前提到的子图同构问题。

posted @ 2020-06-16 17:07  Easonshi  阅读(316)  评论(0)    收藏  举报