你好,游客 登录
背景:
阅读新闻

云计算:淘宝云梯的多NameNode和跨机房之路

[日期:2014-09-15] 来源:编程入门  作者:罗李 [字体: ]

    可以看出,完成了这一步,基本上就解决了前述难点1(NameNode的扩展性问题)。到这一步结束,单点NameNode就变成了多个,原先由一 个 NameNode来承担的对文件系统所有元数据的访问被分摊到了多个NameNode上,NameNode的性能、内存和扩展性问题都不复存在。

    经历完上述三步,实际上云梯已经完成了多NameNode的切分,但数据仍然在一个机房里面,分别由两个NameNode来分别管理。此时将另一个 机房(机 房B)已经准备就绪的Slave机器开始同时向两个NameNode进行汇报。也就是说,将另一个机房的Slave机器进行上线服务。

    第五 步,将NameNode2从原先的机房(机房A)转移到另一个机房(机房B)。这样,两个NameNode从物理机房上就已经分离,只不过 NameNode2上管理的数据所对应的block块仍然分布在机房A,需要对这部分数据(图1中的/group/B和/group/D的blocks) 进行迁移。这里的迁移方式很特殊,云梯团队开发了一个新的Master节点,叫做CrossNode,来实现数据的跨机房分布和跨机房拷贝的策略,将在后 面的内容中详细介绍。

    经过第五步以后,云梯已经达到多NameNode切分,以及数据的NameSpace切分以及相应的block多机房 分布。接下来的一个问题是:如何让底层的这些变更对上层业务完全透明?我们采取的策略是ViewFS。简单地说,ViewFS是云梯开发团队全新开发的一 个实现Client端对多NameNode的透明感知组件,让客户端能够自动找到正确的NameNode来进行数据的读写。实现了ViewFS的的云梯 hadoop Client结构如图2所示。

 

图2 云梯Client架构图

 

    经过客户端的改造和升级,以前老的访问方式由智能的Client接管。由Yunti3FileSystem根据访问路径自动选择要访问的NameNode,实现了数据的分切对客户端透明。也由此解决了前述难点6(怎样做到对用户透明)。

    到此为止,云梯的数据实现了跨机房分布,NameSpace实现了跨机房切分,客户端访问也实现了对用户透明。接下来就是计算调度跨机房的实现。由于MapReduce本身的特征,计算调度很多情况下是跟着数据走的,所以要实现跨机房计算调度,云梯采取的策略如图3所示。

图3 云梯跨机房调度架构图

    从图3可以看出,云梯集群分别在两个机房各启动了一个MapReduce,用来做实际任务的分配和调度,而job在提交到JobTracker之 前,有一个新开发的JTProxy组件来对job的提交进行前提判断。由于云梯的计算资源是按照组来划分的,所以JTProxy要根据计算组的配置来决定 向哪个JobTracker进行job提交。并且JTProxy还提供了一个统一的Web界面供用户查询多个JobTracker上的作业运行情况。至 此,前述难点4(计算应该如何跨机房调度)迎刃而解。

    经过上述多个步骤,云梯集群就实现了多NameNode切分、数据的跨机房分布和管理、计算的 跨机房调度等,虽然物理上云梯集群跨越两个数据中心,但对上层业务来说,完全感知不到底层的变动。不仅如此,由于实现了多Master的切分,让多个 NameNode来分担以前一个NameNode来管理的所有数据,所以也很大程度上释放了以前单NameNode节点在扩展性和性能上的瓶颈,让以前因 为单Master节点带来的种种问题全部都迎刃而解。同时也为将来集群的进一步扩充留下很大的余地。基本上,在基于跨机房的那个版本和框架下,云梯 Hadoop集群几乎是没有物理上限的一个集群了。

    细心的读者肯定发现,难点5的解决方案没有详细说明,下面对此进行详细讲述。

    问题:在上述第三步中,我们怎样将NameNode1中的部分数据(比如50%)迁移到NameNode2,迁移的同时还不影响业务的正常运行呢? (这里的迁移包括NameSpace中的元数据迁移和底下DataNode磁盘中的block)。这个问题本身是一个非常复杂的场景,云梯开发团队也是通 过几个步 骤来一点点地实现的。

    需要先让新的NameNode2获取原先NameNode1上所有的元数据的全量拷贝。这是开发团队通过将 NameNode1上最新的fsimage用到NameNode2上,并进行load来完成的。这样,新的NameNode2就拥有了NameNode1 上所有的文件和目录结构,以及文件的block组成情况,唯一缺的就是每个block在哪些DataNode上的分布情况,这一部分需要通过 DataNode的blockReport来进行构建。

    完成了上述步骤以后,还需要让所有的DataNode上原本的单一 BlockPool变成多个。其中BlockPool1对应原先的DataNode上所有block数据的全量,而BlockPool2则是空。要让 BlockPool2中拥有BlockPool1中的所有block,有两种方式:一种是进行全量拷贝;另一种方式比较讨巧,是将BlockPool1中 的所有block及其对应的目录在BlockPool2中创建全量的hardlink。由于只是磁盘层面的硬连接创建,所以不占额外的存储空间,而且很 快。这样,当所有的DataNode启动时,原本的BlockPool1中的数据向NameNode1汇报,而BlockPool2中拥有的同样一份数据 向NameNode2汇报。这样当集群启动完毕以后,两个NameNode都拥有整个集群数据的元数据全量,只不过底层的存储只有一份,通过硬连接来实现 block块数据共享。

    完成上一步后,集群的状态是:两个NameNode都管理了整个集群的全量数据,但实际上数据切分并不是要让两个 NameNode都管理全量数据,而是分别管理一半的数据(或者根据实际访问需求来进行特定花费)。也就是说,NameNode1上虽然管理了全量,但需 要删掉一部分不由它管理的数据,NameNode2也是一样,而两个NameNode管理的数据的总和就是原本的全量数据。由于底层block进行了硬连 接的创建,所以只要不在两个NameNode上都删掉同一份数据,那么数据本身在DataNode上就不会丢失。接下来还需要完成两件事:第一,客户端能 根据不同的目录访问特定的NameNode(数据切分);第二,将仍在A机房但需要迁移到B机房的那部分数据(NameNode2应该管理的那部分数据) 的block块迁移到B机房。





收藏 推荐 打印 | 录入: | 阅读:
本文评论   查看全部评论 (0)
表情: 表情 姓名: 字数
点评:
       
评论声明
  • 尊重网上道德,遵守中华人民共和国的各项有关法律法规
  • 承担一切因您的行为而直接或间接导致的民事或刑事法律责任
  • 本站管理人员有权保留或删除其管辖留言中的任意内容
  • 本站有权在网站内转载或引用您的评论
  • 参与本评论即表明您已经阅读并接受上述条款