MST在MapReduce下的实现

48 阅读7分钟

目的及要求

给定一个图<V,E>,基于MapReduce设计实现最小生成树算法,找到给定图的最小生成树。搭建的Hadoop开发环境,至少包含一个name node和一个data node。

实验环境

运行环境:Ubuntu18.04、开发IDE:IDEA

实验内容与步骤

基于docker搭建Hadoop集群环境

Hadoop目前版本已更新到V3,指令和端口与V2相比有不少变化。

端口名称Hadoop 2.xHadoop 3.x
NameNode内部通信端口8020/90008020/9000/9820
NameNode HTTP UI500709870
MapReduce查看执行任务端口80888088
历史服务器通信端口1988819888

本文使用docker compose对Hadoop各组件进行编排,可满足自定义和快速部署测试的需求,节点角色和主机映射关系如下表。

 hadoop-masterhadoop-slave1hadoop-slave2
HDFSNameNode、SecondaryNameNodeDataNodeDataNode
YARNResourceManager、LogServerNodeManagerNodeManager

在原有Github项目的基础上,本文做了以下工作:

① 升级Hadoop版本为官网最新版本3.2.4,处理参数名称变更,配置文件重命名等问题。

② 原有项目是通过docker命令行执行启动,不方便暂停容器、重启容器等操作,本文通过docker compose对容器进行编排,设置挂载目录和端口映射信息,将docker-compose.yml与Dockerfile文件进行联动,方便后续升级。

③ 添加历史日志聚合功能,查看Mapper、Reducer数量和执行时间。

首先从Hadoop官网下载最新安装包,放入与Dockerfile同级目录下,在原始镜像Ubuntu18.04的基础上,安装openssh-server、openjdk-8-jdk,国内可通过清华源进行加速。
替换ssh的配置文件ssh_config如下,即不对新的ssh连接进行公钥确认。

Host localhost
  StrictHostKeyChecking no
Host 0.0.0.0
  StrictHostKeyChecking no
Host hadoop-*
   StrictHostKeyChecking no
   UserKnownHostsFile=/dev/null

同时将ssh产生的公钥加入到已知密钥中,因为开发环境下,多个Hadoop节点会共用一个镜像,所以远端的ssh密钥已经添加到authorized_keys文件中,认证通过,Dockerfile中相关命令如下。

RUN ssh-keygen -t rsa -f ~/.ssh/id_rsa -P '' && \
    cat ~/.ssh/id_rsa.pub >> ~/.ssh/authorized_keys

在Hadoop配置文件中指明节点角色,需要修改的配置文件和内容如下:

配置文件名称配置项配置说明
hadoop-env.shJAVA_HOMEJAVA路径
core-site.xmlhadoop.tmp.dir、fs.defaultFS数据存储目录、NameNode地址
hdfs-site.xmldfs.namenode.name.dir、dfs.datanode.data.dir、dfs.replicationLog日志路径、数据路径、数据副本数
mapred-site.xmlmapreduce.framework.name、mapreduce.jobhistory.address、mapreduce.jobhistory.webapp.address 配置yarn作为底层控制、内部历史服务器地址、外部历史服务器地址 
yarn-site.xmlyarn.nodemanager.aux-services、mapreduce_shuffle.class、yarn.resourcemanager.hostname、yarn.log-aggregation-enable、yarn.log.server.url、yarn.log-aggregation.retain-seconds配置 NodeManager 上运行的服务、mapreduce启动类设置、ResourceManager节点地址、开启日志聚合、yarn的聚合日志地址、日志保留时间
workershadoop-slave1hadoop-slave2每行的主机上都会运行DataNode和NodeManager

在Dockerfile中通过COPY、RUN等原语拷贝配置文件到工作目录,执行hdfs namenode -format初始化HDFS。

接下来在docker-compose.yml配置端口映射、目录映射信息,Hadoop所有节点加入名为hadoop的独立网络,避免地址冲突。需要映射的端口为9870、8088、19888,ssh端口不需要映射,用户通过docker exec命令进入容器内执行命令,另外由于运行docker compose时镜像还未构建,可以在docker-compose.yml配置自动构建的语句,新构建的基于Docker-compose的Hadoop部署链接

hadoop-master:
    image: hadoop-toy:1.0
    build:
      context: .
      dockerfile: Dockerfile
......

hadoop-slavex:
......
    depends_on:
      - hadoop-master

最小生成树

在一个具有N个顶点的带权连通图G中,如果存在某个子图G’,其包含了图G中的所有顶点和一部分边,且不形成回路,并且子图G’的各边权值之和最小,则称G’为图G的最小生成树。

常用的最小生成树算法有KruskalPrimBoruvka

Kruskal的核心思想是它直接选边,在找最小生成树结点之前,需要对所有权重边做从小到大排序,将排序好的权重边依次加入到最小生成树中,如果加入时产生回路就跳过这条边,当所有结点都加入到最小生成树中之后,就找出了最小生成树。而Prim算法操作的对象是结点,它首先以一个结点作为最小生成树的初始结点,然后以迭代的方式找出与最小生成树中各结点权重最小边,并加入到最小生成树中,加入之后如果产生回路则跳过这条边。最后Boruvka算法的操作对象则是集合,多个连通结点构成一个集合,算法描述如下:

① 输入一个连通的有向带权图。

② 把所有顶点都初始化成单独的一个子集。

③ 初始化一个空的MST。

④ 只要子集个数大于1,就对依次各个子集合执行以下操作:找出所有与当前集合有边相连的集合,选出权重最小的那条边(设为minEdge);如果minEdge不存在于MST中,则把minEdge添加到MST中。

⑤ MST求得,算法结束。

本文首先基于MapReduce在shuffle阶段自动按键排序的特点,测试基于Kruskal算法得到最小生成树,程序逻辑如下。

map-1.png

先将输入文件存入HDFS。 图片6.png

然后把IDEA打包好的jar包拖入共享文件夹内,选择不带依赖的版本即可,远端已经具备依赖包。 图片7.png

然后在命令行输入以下命令进行测试。

hadoop jar HadoopApp.jar lkh.hadoop.demo.MST mediumEWG.txt output 2 1

其中第一个参数为输入文件路径,第二个参数为输出文件路径,第三个参数为mapper阶段的切割单元,单位为KB,根据此项设置mapper的数量,第四个参数为reducer的数量。运行程序时必须保证输出文件夹不存在,如已存在,可使用hdfs dfs -rm -r ouput命令删除。

在历史日志服务器查看执行日志。   图片8.png

但是经测试,发现只有在单个Reducer时,该最小生成树算法是有效,结果如下。

图片9.png 当多于1个reducer时,算法无法维护全局的节点连接信息,最终得到的边数显然不符合最小生成树要求。

图片10.png

Karlof等人[2,3]引入新的最小生成树算法可以在多reducer情境下进行,算法思想是多个局部最小生成树能构成全局最小生成树,2个mapreduce阶段作为1个处理回合,整体算法逻辑如下图所示。

map-2.png

实验结果与数据处理

接下来测试Karlof算法性能在mapreduce环境的影响因素。

在mapper数量恒定为1的情况下,运行时间和reducer数量、图规模关系如下图所示。

图片11.png

在reducer数量恒定为1的情况下,运行时间和mapper数量、图规模关系如下图所示。

图片12.png

通过以上数据可以发现,在最小生成树场景下,程序的耗时主要在mapper阶段,并行化reduce不会带来很多提升,另外更多的mapper、reducer意味着更多的程序切换开销,所以出现更多reducer反而耗时更多的状况。在reducer数量一定时,数据量更大的计算受mapper影响更大,这也是Hadoop设计的主要目的。

 

分析与讨论

本文对MapReduce环境下的最小生成树算法进行了讨论,常见的单机算法并不适合MapReduce模式,因为数据总是分散在多个Reducer节点上,无法实现全局的搜索。研究人员提出的新算法[3,4]通过冗余边信息,实现从局部解推出全局解的目标,本文最后对其中的Karlof算法进行测试,发现MapReduce更适合大数据量、耗时长等任务,但是该实验也存在缺陷,算法最后会调整reducer数量,将经过前序筛选后的节点放入同一计算reducer,加快生成树速度。

  参考文献:

[1] guillermobet. MapReduceMST. github.com/guillermobe…. Accessed July 14, 2022.
[2] ganeshskudva. MinimumS panningT ree. https : / / github . com / ganeshskudva / Minimum _ Spanning _ Tree.Accessed July 14.
[3] Karloff H, Suri S, Vassilvitskii S. A model of computation for mapreduce[C]//Proceedings of the twenty-first annual ACM-SIAM symposium on Discrete Algorithms. Society for Industrial and Applied Mathematics, 2010: 938-948.
[4] Lattanzi S, Moseley B, Suri S, et al. Filtering: a method for solving graph problems in mapreduce[C]//Proceedings of the twenty-third annual ACM symposium on Parallelism in algorithms and architectures. 2011: 85-94.