分布式存储与分布式计算

总结很不错,就转过来了,原博文:http://blog.csdn.net/recommender_system/article/details/42024205

一、高性能计算

目前自己知道的高性能计算工具,如下所示:

  • Hadoop:Hadoop的框架最核心的设计就是:HDFS和MapReduce。HDFS为海量的数据提供了存储,则MapReduce为海量的数据提供了计算。
  • Spark:Spark是UC Berkeley AMP lab所开源的类Hadoop MapReduce的通用的并行,Spark,拥有Hadoop MapReduce所具有的优点;但不同于MapReduce的是Job中间输出结果可以保存在内存中,从而不再需要读写HDFS,因此Spark能更好地适用于数据挖掘与机器学习等需要迭代的map reduce的算法。
  • CUDA:CUDA(Compute Unified Device Architecture),是显卡厂商NVIDIA推出的运算平台。 CUDA是一种由NVIDIA推出的通用并行计算架构,该架构使GPU能够解决复杂的计算问题。 它包含了CUDA指令集架构(ISA)以及GPU内部的并行计算引擎。 开发人员现在可以使用C语言来为CUDA架构编写程序,C语言是应用最广泛的一种高级编程语言。所编写出的程序于是就可以在支持CUDA的处理器上以超高性能运行。CUDA3.0已经开始支持C++和FORTRAN。
  • OpenCL:OpenCL(全称Open Computing Language,开放运算语言)是第一个面向异构系统通用目的并行编程的开放式、免费标准,也是一个统一的编程环境,便于软件开发人员为高性能计算服务器、桌面计算系统、手持设备编写高效轻便的代码,而且广泛适用于多核心处理器(CPU)、图形处理器(GPU)、Cell类型架构以及数字信号处理器(DSP)等其他并行处理器,在游戏、娱乐、科研、医疗等各种领域都有广阔的发展前景。
  • MPICH:通过安装MPICH构建MPI编程环境,从而进行并行程序的开发。MPICH是MPI(Message-Passing Interface)的一个应用实现,支持最新的MPI-2接口标准,是用于并行运算的工具。
  • MPI:MPI是一个跨语言的通讯协议,用于编写并行计算机。支持点对点和广播。MPI是一个信息传递应用程序接口,包括协议和和语义说明,他们指明其如何在各种实现中发挥其特性。MPI的目标是高性能,大规模性,和可移植性。MPI在今天仍为高性能计算的主要模型。主要的MPI-1模型不包括共享内存概念,MPI-2只有有限的分布共享内存概念。 但是MPI程序经常在共享内存的机器上运行。在MPI模型周边设计程序比在NUMA架构下设计要好因为MPI鼓励内存本地化。尽管MPI属于OSI参考模型的第五层或者更高,他的实现可能通过传输层的sockets和Transmission Control Protocol (TCP)覆盖大部分的层。大部分的MPI实现由一些指定惯例集(API)组成,可由C,C++,Fortran或者有此类库的语言比如C#,Java或者Python直接调用。MPI优于老式信息传递库是因为他的可移植性和速度。
  • OpenMPI:OpenMPI是一种高性能消息传递库,最初是作为融合的技术和资源从其他几个项目(FT-MPI,LA-MPI,LAM/MPI以及PACX-MPI),它是MPI-2标准的一个开源实现,由一些科研机构和企业一起开发和维护。因此,OpenMPI能够从高性能社区中获得专业技术、工业技术和资源支持,来创建最好的MPI库。OpenMPI提供给系统和软件供应商、程序开发者和研究人员很多便利。易于使用,并运行本身在各种各样的操作系统,网络互连,以及一批/调度系统。
  • OpenMP:OpenMp是由OpenMP Architecture Review Board牵头提出的,并已被广泛接受的,用于共享内存并行系统的多线程程序设计的一套指导性的编译处理方案(Compiler Directive)。OpenMP支持的编程语言包括C语言、C++和Fortran;而支持OpenMp的编译器包括Sun Compiler,GNU Compiler和Intel Compiler等。OpenMp提供了对并行算法的高层的抽象描述,程序员通过在源代码中加入专用的pragma来指明自己的意图,由此编译器可以自动将程序进行并行化,并在必要之处加入同步互斥以及通信。当选择忽略这些pragma,或者编译器不支持OpenMp时,程序又可退化为通常的程序(一般为串行),代码仍然可以正常运作,只是不能利用多线程来加速程序执行。
  • GraphLab:GraphLab 是另一种有趣的MapReduce抽象实现,侧重机器学习算法的并行实现。GraphLab中,Map阶段定义了可以独立执行(在独立的主机上)的计算,Reduce阶段合并这些计算结果。
说明:
(1)高性能计算:集群,多线程,分布式,并行计算。
(2)计算机存储容量单位:1B=8bit;1KB=1024B;1MB=1024KB;1GB=1024MB;1TB=1024GB;1PB=1024TB;1EB=1024PB;1ZB=1024EB;1YB=1024ZB;1NB=1024YB;1DB=1024NB;1CB=1024DB。

二、Hadoop生态系统

1、Hadoop生态系统的功能以及对应的开源工具,如下所示:

(1)海量数据怎么存,当然是用分布式文件系统——HDFS。

(2)数据怎么用呢,分析、处理MapReduce框架,让你通过编写代码来实现对大数据的分析工作。

(3)非结构化数据(日志)收集处理——Fuse、WebDAV、Chukwa、Flume和Scribe。

(4)数据导入HDFS中,RDBMS也可以加入HDFS的狂欢了——HIHO、Sqoop。

(5)MaoReduce太麻烦,用熟悉的方式操作Hadoop里的数据——Pig、Hive、Jaql。

(6)让你的数据可见——Drilldown、Intellicus。

(7)用高级语言管理你的任务流——Oozie、Cascading。

(8)Hadoop自己的监控管理工具——Hue、Karmasphere、Eclipse Plugin、Cacti、Ganglia。

(9)数据序列化处理与任务调度——Avro、ZooKeeper。

(10)更多构建在Hadoop上层的服务——Mahout、Elastic Map Reduce。

(11)OLTP存储系统——HBase。

(12)基于Hadoop的实时分析——Impala。

2、Hadoop常用项目介绍

(1)Apache Hadoop

Hadoop是一个大数据处理框架,它可用于从单台到数以千计的服务器集群的存储和计算服务。HadoopDistributed File System (HDFS) 提供了能够跨越多台计算机的大数据存储服务,而MapReduce则提供了一个并行处理的框架。它们的思想源自Google的MapReduce和Google File System(GFS)论文。详细参见:http://hadoop.apache.org/

(2)Apache Ambari

Ambari是一个对Hadoop集群进行监控和管理的基于Web的系统。目前已经支持HDFS,MapReduce,Hive,HCatalog,HBase,ZooKeeper,Oozie,Pig和Sqoop等组件。详细参见:http://ambari.apache.org/

(3)Apache Cassandra

Cassandra是一个分布式的NoSQL数据库。它基于multi-master模式,无单点失败,具有可扩展性。最早由Facebook开发用于存储收件箱等简单格式数据,后开源,被用于Twitter等知名网站。详细参见:http://cassandra.apache.org/

(4)Apache Hive

Hive是 一个数据仓库工具,可以将结构化的数据文件映射为一张数据库表,并提供类似SQL一样的查询语言HiveQL来管理这些数据。详细参见:http://hive.apache.org/

(5)Apache Pig

Pig是一个基于Hadoop的大数据分析平台,它提供了一个叫PigLatin的高级语言来表达大数据分析程序。详细参见:http://pig.apache.org/

(6)Apache Avro

Avro是一个数据序列化系统。它提供了丰富的数据结构类型,快读可压缩的二进制数据格式,存储持久数据的文件容器,远程过程调用等。详细参见:http://avro.apache.org/

(7)Apache Chukwa

Chukwa是一个用于监控大型分布式系统的的数据采集系统。它构建于Hadoop的HDFS和Map/Reduce框架之上,包含了一系列用于数据监控,分析和展示的灵活的强大工具集。它为日志系统提供了一整套解决方案。详细参见:http://chukwa.apache.org/

(8)Apache Drill

Drill是一个对大规模数据集进行交互式分析的分布式系统。它是Google的Gremel的开源实现。详细参见:http://incubator.apache.org/drill/

(9)Apache Flume

Flume是一个高可靠的分布式海量日志采集,聚合和传输系统。它来源于Cloudera开发的日志收集系统。详细参见:http://flume.apache.org/

(10)Apache HBase

HBase是一个分布式的,面向列的数据库。它基于Hadoop之上提供了类似BigTable的功能。详细参见:http://hbase.apache.org/

(11)Apache HCatalog

HCatalog是基于Hadoop的数据表和存储管理服务,提供了更好的数据存储抽象和元数据服务。详细参见:https://hive.apache.org/hcatalog/

(12)Apache Mahout 

Mahout是一个机器学习领域的经典算法库,提供包括聚类,分类,推荐过滤,频繁子项挖掘等。详细参见:http://mahout.apache.org/

(13)Apache Oozie 

Oozie是一个工作流调度系统,用于管理Hadoop里的job。它可以把多个Map/Reduce作业组合到一个逻辑工作单元来完成指定目标。详细参见:http://oozie.apache.org/

(14)Apache Sqoop

Sqoop是一个Hadoop和关系型数据库之间的数据转移工具。可将关系型数据库中的数据导入到Hadoop的HDFS中,也可将HDFS中的数据导进到关系型数据库中。详细参见:http://sqoop.apache.org/

(15)Apache ZooKeeper

ZooKeeper是一个针对大型分布式系统的可靠协调系统,提供包括配置维护,名字服务,分布式同步和组服务等功能。Hadoop的管理就是用的ZooKeeper。详细参见:http://zookeeper.apache.org

(16)Apache Giraph

Giraph是一个高可伸缩的迭代式图处理系统。它现在用于分析Facebook中的用户的社交关系。Giraph相当于Google图处理架构Pregel的开源版本。详细参见:http://giraph.apache.org/

(17)Apache Accumulo 

Accumulo是一个可靠的,可伸缩的,高性能排序分布式的Key-Value存储解决方案。它基于Google的BigTable设计思路。详细参见:http://accumulo.apache.org/

(18)Apache S4

S4是一个可扩展的,分布式的流数据实时处理框架,最早由Yahoo开发并开源。与Twitter的Storm类似。详细参见:http://incubator.apache.org/s4/

(19)Apache Thrift

Thrift是一个跨语言的服务开发框架。用它可让你的服务支持多种语言的开发,并可用代码生成器对它所定义的IDL定义文件自动生成服务代码框架。它最早由Facebook开发并开源出来。 详细参见:http://thrift.apache.org/

(20)Impala

Impala采用与Hive相同的元数据、SQL语法、ODBC驱动程序和用户接口(Hue Beeswax),这样在使用CDH产品时,批处理和实时查询的平台是统一的。目前支持的文件格式是文本文件和Sequence Files(可以压缩为Snappy、GZIP和BZIP,前者性能最好)。其他格式如Avro、RCFile、LZO文本和Doug Cutting的Trevni将在正式版中支持,官方测试速度是Hive的3~90倍。详细参见:http://www.cloudera.com/content/cloudera/en/products-and-services/cdh/impala.html

(21)Nutch

最后,得提一下Apache Nutch开源网络爬虫系统。Hadoop最早是为Nutch服务而诞生的,即为大规模的网络爬虫系统提供分布式存储和计算服务。详细参见:https://nutch.apache.org/

说明:

开源的搜索引擎工具:Lucene,Nutch,Solr。

3、Hadoop应用场景

美国著名科技博客GigaOM的专栏作家Derrick Harris跟踪云计算和Hadoop技术已有多年时间,他也在最近的一篇文章中总结了10个Hadoop的应用场景,如下所示:
(1)在线旅游

你知道吗,目前全球范围内80%的在线旅游网站都是在使用Cloudera公司提供的Hadoop发行版,其中SearchBI网站曾经报道过的Expedia也在其中。
(2)移动数据

Cloudera运营总监称,美国有70%的智能手机数据服务背后都是由Hadoop来支撑的,也就是说,包括数据的存储以及无线运营商的数据处理等,都是在利用Hadoop技术。
(3)电子商务

这一场景应该是非常确定的,eBay就是最大的实践者之一。国内的电商在Hadoop技术上也是储备颇为雄厚的。
(4)能源开采

美国Chevron公司是全美第二大石油公司,他们的IT部门主管介绍了Chevron使用Hadoop的经验,他们利用Hadoop进行数据的收集和处理,其中这些数据是海洋的地震数据,以便于他们找到油矿的位置。
(5)节能

另外一家能源服务商Opower也在使用Hadoop,为消费者提供节约电费的服务,其中对用户电费单进行了预测分析。
(6)基础架构管理

这是一个非常基础的应用场景,用户可以用Hadoop从服务器、交换机以及其他的设备中收集并分析数据。
(7)图像处理

创业公司Skybox Imaging 使用Hadoop来存储并处理图片数据,从卫星中拍摄的高清图像中探测地理变化。
(8)诈骗检测

这个场景用户接触的比较少,一般金融服务或者政府机构会用到。利用Hadoop来存储所有的客户交易数据,包括一些非结构化的数据,能够帮助机构发现客户的异常活动,预防欺诈行为。
(9)IT安全

除企业IT基础机构的管理之外,Hadoop还可以用来处理机器生成数据以便甄别来自恶意软件或者网络中的攻击。
(10)医疗保健

医疗行业也会用到Hadoop,像IBM的Watson就会使用Hadoop集群作为其服务的基础,包括语义分析等高级分析技术等。医疗机构可以利用语义分析为患者提供医护人员,并协助医生更好地为患者进行诊断。


三、YARN

       记得1.5年前的时候,首次接触Hadoop,那个时候Hadoop 2.X版本还没有出来,Spark也没有现在这么热。现在,Hadoop 2.X都出来快一年了,开源软件的发展速度之快,令人惊叹。以前Hadoop的学习都是比较零散的,不够系统,现在决定系统地、深入地学习Hadoop。掌握其精髓所在,即软件的工作原理和设计理念,而不忙于跟风,要深入地学习开发和运维,而不是盲目地追新,做安装卸载这样的重复性工作。总之,打牢HDFS和MapReduce基础,根据需要,逐步学习Hadoop的整个生态系统。

      Hadoop 2.X最大的变化当然是YARN这个资源管理器了,或者说Hadoop操作系统了。YARN是Hadoop 2.0及以上版本的下一代集群资源管理和调度平台,支持多种计算框架,不仅支持MapReduce计算框架,还可以支持流式计算框架、图计算框架、实时/内存计算框架等,极大地扩展了Hadoop的使用场景,提高了Hadoop集群的利用效率。

说明:

集群资源管理和调度平台,除了YARN之外,还有Corona和Mesos等。


四、DRCP(Distributed Recommend Computing Platform)

1. Introduction

DRCP is a Distributed Machine Learning Platform based on Mahout,the functions are Distributed Storage and Distributed Computing, which is usedto scientific research and learning.

2.  Topology


3. Software

(1)jdk-1.7.0

(2)hadoop-0.20.2

(3) mahout-0.5.0

(4)ubuntu-12.04


五、开发运维

       最近在实验室搭建了一个4台Hadoop集群,在上面部署了分布式机器学习Mahout这个软件,我们的目的主要是为了做大数据推荐算法,提供一个生产平台。当然,4台Hadoop集群是远远不够的,以后会考虑升级的。通过这个真实的生产平台,提高MapReduce应用开发的能力,Hadoop和Mahout二次开发的能力,以及Hadoop运维的能力(调优)。打算在DRCP上开发我们的大数据推荐算法类库——Conquer,把一些经典的推荐算法,机器学习算法等,还有我们的研究成果MapReduce化之后融入到Conquer之中,到时候会开源的。

1、DRCP的升级

  • 添加结点
  • 删除结点
  • 系统升级
  • 软件安装
  • 软件卸载

2、DRCP的运维

  • 系统优化

参考文献:

[11] Hadoop应用场景: http://www.ciotimes.com/infrastructure/syjq/67136.html



MapReduce工作原理


一、MapReduce模型框架

       MapReduce是一个用于大规模数据处理的分布式计算模型,最初由Google工程师设计并实现的,Google已经将完整的MapReduce论文公开发布了。其中的定义是,MapReduce是一个编程模型,是一个用于处理和生成大规模数据集的相关的实现。用户定义一个map函数来处理一个Key-Value对以生成一批中间的Key-Value对,再定义一个reduce函数将所有这些中间的有相同Key的Value合并起来。很多现实世界中的任务都可用这个模型来表达。

1、MapReduce模型


源数据                                 中间数据                  结果数据

MapReduce模型如上图所示,Hadoop MapReduce模型主要有Mapper和Reducer两个抽象类。Mapper端主要负责对数据的分析处理,最终转化为Key-Value的数据结构;Reducer端主要是获取Mapper出来的结果,对结果进行统计。


2、MapReduce框架


整个过程如上图所示,包含4个独立的实体,如下所示:

  • client:提交MapReduce作业,比如,写的MR程序,还有CLI执行的命令等。
  • jobtracker:协调作业的运行,就是一个管理者。
  • tasktracker:运行作业划分后的任务,就是一个执行者。
  • hdfs:用来在集群间共享存储的一种抽象的文件系统。
说明:
其实,还有namenode就是一个元数据仓库,就行windows中的注册表一样。secondarynamenode可以看成namenode的备份。datanode可以看成是用来存储作业划分后的任务。在DRCP中,master是namenode,secondarynamenode,jobtracker,其它的3台slaver都是tasktracker,datanode,且tasktracker都需要运行在HDFS的datanode上面。
MapReduce框架中组成部分及它们之间的关系,如下所示:
  • Mapper和Reducer
运行在Hadoop上的MapReduce应用程序最基本的组成部分包括:一是Mapper抽象类,一是Reducer抽象类,一是创建JobConf的执行程序。
  • JobTracker
JobTracker是一个master服务,软件启动之后JobTracker接收Job,负责调度Job的每一个子任务Task运行于TaskTracker上,并且监控它们的运行,如果发现有失败的Task就重新运行它,一般情况下应该把JobTracker部署在单独的机器上。
  • TaskTracker
TaskTracker是运行在多个节点上的slaver服务。TaskTracker主动与JobTracker通信(与DataNode和NameNode相似,通过心跳来实现)接收作业,并负责直接执行每一个任务。
  • JobClient
每一个Job都会在用户端通过JobClient类将应用程序以及配置参数Configuration打包成JAR文件存储在HDFS中,并把路径提交到JobTracker的master服务,然后由master创建每一个Task(即MapTask和ReduceTask)将它们分发到各个TaskTracker服务中去执行。
  • JobInProgress
JobClient提交Job后,JobTracker会创建一个JobInProgress来跟踪和调度这个Job,并把它添加到Job队列之中。JobInProgress会根据提交的任务JAR中定义的输入数据集(已分解成FileSplit)创建对应的一批TaskInProgress用于监控和调度MapTask,同时创建指定书目的TaskInProgress用于监控和调度ReduceTask,默认为1个ReduceTask。
  • TaskInProgress
JobTracker启动任务时通过每一个TaskInProgress来运行Task,这时会把Task对象(即MapTask和ReduceTask)序列化写入相应的TaskTracker服务中,TaskTracker收到后会创建对应的TaskInProgress(此TaskInProgress实现非JobTracker中使用的TaskInProgress,作用类似)用于监控和调度该Task。启动具体的Task进程通过TaskInProgress管理,通过TaskRunner对象来运行。TaskRunner会自动装载任务JAR文件并设置好环境变量后,启动一个独立的Java Child进程来执行Task,即MapTask或者ReduceTask,但它们不一定运行在同一个TaskTracker中。
  • MapTask和ReduceTask
一个完整的Job会自动依次执行Mapper、Combiner(在JobConf指定Combiner时执行)和Reducer,其中Mapper和Combiner是由MapTask调用执行,Reduce则由ReduceTask调用,Combiner实际也是Reducer接口类的实现。Mapper会根据Job JAR中定义的输入数据集<key1, value1>对读入,处理完成生成临时的<key2, value2>对,如果定义了Combiner,MapTask会在Mapper完成调用该Combiner将相同Key的值做合并处理,以减少输出结果集。MapTask的任务全部完成后,交给ReduceTask进程调用Reducer处理,生成最终结果<Key3, value3>对。

二、MapReduce工作原理


1、作业的提交
JobClient的submitJob()方法实现的作业提交过程,如下所示:
  • 通过JobTracker的getNewJobId()方法,向jobtracker请求一个新的作业ID。参见步骤2。
  • 检查作业的输出说明,也就是说要指定输出目录的路径,但是输出目录还不能存在(防止覆盖输出结果),如果不满足条件,就会将错误抛给MapReduce程序。
  • 检查作业的输入说明,也就是说如果输入路径不存在,作业也没法提交,如果不满足条件,就会将错误抛给MapReduce程序。
  • 将作业运行所需的资源,比如作业JAR文件、配置文件等复制到HDFS中。参见步骤3。
  • 通过JobTracker的submitJob()方法,告诉jobtracker作业准备执行。参见步骤4。
2、作业的初始化
  • JobTracker接收到对其submitJob()方法调用之后,就会把此调用放入一个内部队列当中,交由作业调度器进行调度。(说明:Hadoop作业的调度器常见的有3个:先进先出调度器;容量调度器;公平调度器。Hadoop作业调度器采用的是插件机制,即作业调度器是动态加载的、可插拔的,同时第三方可以开发自己的作业调度器,参考资料"大规模分布式系统架构与设计实战")。参见步骤5。
  • 初始化包括创建一个表示正在运行作业的对象——封装任务的记录信息,以便跟踪任务的状态和进程。参见步骤5。
  • 接下来要创建运行任务列表,作业调度器首先从共享文件系统中获取JobClient已计算好的输入分片信息,然后为每个分片创建一个map任务(也就是说mapper的个数与分片的数目相同)。参见步骤6。(创建reduce任务的数量由JobConf的mapred.reduce.task属性决定,它是用setNumReduceTasks()方法来设置的,然后调度器创建相应数量的要运行的reduce任务,默认情况只有一个reducer)
3、任务的分配
  • tasktracker本身运行一个简单的循环来定期发送"心跳(heartbeat)"给jobtracker。什么是心跳呢?就是tasktracker告诉jobtracker它是否还活着,同时心跳也充当两者之间的消息通信,比如tasktracker会指明它是否已经做好准备来运行新的任务了,如果是,管理者jobtracker就会给执行者tasktracker分配一个任务。参见步骤7。
  • 当然,在管理者jobtracker为执行者tasktracker选择任务之前,jobtracker必须先选定任务所在的作业。一旦选择好作业,jobtracker就可以给tasktracker选定一个任务。如何选择一个作业呢?当然是Hadoop作业的调度器了,它就像是Hadoop的中枢神经系统一样,默认的方法是简单维护一个作业优先级列表。(对于调度算法的更深理解可以学习操作系统的作业调度算法,进程调度算法,比如先来先服务(FCFS)调度算法,短作业优先(SJF)调度算法,优先级调度算法,高响应比优先调度算法,时间片轮转调度算法,多级反馈队列调度算法等。如果从更高的角度来看调度算法,其实是一种控制和决策的策略选择。)
4、任务的执行
  • 作业选择好了,任务也选择好了,接下来要做的事情就是任务的运行了。首先,从HDFS中把作业的JAR文件复制到tasktracker所在的文件系统,同时,tasktracker将应用程序所需要的全部文件从分布式缓存复制到本地磁盘,也就是从HDFS文件系统复制到ext4等文件系统之中。参见步骤8。
  • tasktracker为任务新建一个本地工作目录,并把JAR文件中的内容解压到这个文件夹中,新建一个TaskRunner实例来运行该任务。
  • TaskRunner启动一个新的JVM(参见步骤9)来运行每个任务(参见步骤10),以便用户定义的map和reduce函数的任何缺陷都不会影响TaskTracker守护进程(比如导致它崩溃或者挂起)。需要说明一点的是,对于map和reduce任务,tasktracker有固定数量的任务槽,准确数量由tasktracker核的数量和内存大小来决定,比如一个tasktracker可能同时运行两个map任务和reduce任务。map任务和reduce任务中关于数据本地化部分不再讲解,因为DRCP没有用到,只要理解本地数据级别就可以了,比如node-local,rack-local,off-switch。
  • 子进程通过umbilical接口与父进程进行通信,任务的子进程每隔几秒便告诉父进程它的进度,直到任务完成。
5、进度和状态的更新

  • MapReduce是Hadoop的一个离线计算框架,运行时间范围从数秒到数小时,因此,对于我们而言直到作业进展是很重要的。
  • 一个作业和每个任务都有一个状态信息,包括作业或任务的运行状态(比如,运行状态,成功完成,失败状态)、Map和Reduce的进度、计数器值、状态消息和描述(可以由用户代码来设置)等。
  • 这些消息通过一定的时间间隔由Child JVM—>TaskTracker—>JobTracker汇聚。JobTracker将产生一个表明所有运行作业及其任务状态的全局视图。可以通过Web UI查看。同时JobClient通过每秒查询JobTracker来获得最新状态,输出到控制台上。
  • 现在可能会有一个疑问,这些状态信息在作业执行期间不断变化,它们是如何与客户端进行通信的呢?详细细节不在讲解,参考资料《Hadoop权威指南》。
6、作业的完成
  • 当jobtracker收到作业最后一个任务已完成的通知后,便把作业的状态设置为"成功"。然后,在JobClient查询状态时,便知道作业已成功完成,于是JobClient打印一条消息告知用户,最后从runJob()方法返回。
说明:
MapReduce容错,即作业失败情况不再讲解,参考资料《Hadoop权威指南》。

三、Shuffle阶段和Sort阶段

如果说以上是从物理实体的角度来讲解MapReduce的工作原理,那么以上便是从逻辑实体的角度来讲解MapReduce的工作原理,如下所示:
  1. 输入分片: 在进行map计算之前,mapreduce会根据输入文件计算输入分片,每个输入分片针对一个map任务,输入分片存储的并非数据本身,而是一个分片长度和一个记录数据位置的数组,输入分片往往和hdfs的block关系很密切。假如我们设定hdfs块的大小是64MB,如果我们有三个输入文件,大小分别是3MB、65MB和127MB,那么mapreduce会把3MB文件分为一个输入分片,65MB则是两个输入分片,而127MB也是两个输入分片,就会有5个map任务将执行。
  2. map阶段: 就是编写好的map函数,而且一般map操作都是本地化操作,也就是在数据存储节点上进行。
  3. combiner阶段: combiner阶段是可以选择的,combiner本质也是一种reduce操作。Combiner是一个本地化的reduce操作,它是map运算的后续操作,主要是在map计算出中间文件后做一个简单的合并重复key值的操作,比如,我们对文件里的单词频率做统计,如果map计算时候碰到一个hadoop单词就会记录为1,这篇文章里hadoop可能会出现多次,那么map输出文件冗余就会很多,因此在reduce计算前对相同的key做一个合并操作,文件就会变小,这样就提高了宽带的传输效率。但是combiner操作是有风险的,使用它的原则是combiner的输入不会影响到reduce计算的最终结果,比如:如果计算只是求总数,最大值,最小值可以使用combiner,但是如果做平均值计算使用combiner,那么最终的reduce计算结果就会出错。
  4. shuffle阶段: 将map的输出作为reduce输入的过程就是shuffle。一般mapreduce计算的都是海量数据,map输出的时候不可能把所有文件都放到内存中进行操作,因此map写入磁盘的过程十分的复杂,更何况map输出的时候要对结果进行排序,内存开销是很大的。map在做输出的时候会在内存里开启一个环形内存缓冲区,这个缓冲区是专门用来输出的,默认大小是100MB,并且在配置文件里为这个缓冲区设定了一个阀值,默认是0.80(这个大小和阀值都是可以在配置文件里进行配置的),同时map还会为输出操作启动一个守护线程,如果缓冲区的内存达到了阀值的80%时候,这个守护线程就会把内容写到磁盘上,这个过程叫spill。另外的20%内存可以继续写入要写进磁盘的数据,写出磁盘和写入内存操作是互不干扰的,如果缓存区被填满了,那么map就会阻塞写入内存的操作,让写出磁盘操作完成后再继续执行写入内存操作。写出磁盘前会有个排序操作,这个是在写出磁盘操作的时候进行的,不是在写入内存的时候进行的,如果还定义了combiner函数,那么排序后还会执行combiner操作。每次spill操作也就是写出磁盘操作的时候就会写一个溢出文件,即在做map输出的时候有几次spill操作就会产生多少个溢出文件。这个过程里还会有一个partitioner操作,其实partitioner操作和map阶段的输入分片很像,一个partitioner对应一个reduce作业,如果mapreduce操作只有一个reduce操作,那么partitioner就只有一个。如果有多个reduce操作,那么partitioner对应的就会有多个。因此,可以把partitioner看作reduce的输入分片。到了reduce阶段就是合并map输出文件,partitioner会找到对应的map输出文件,然后进行复制操作,复制操作时reduce会开启几个复制线程,这些线程默认个数是5个(也可以在配置文件中更改复制线程的个数),这个复制过程和map写出磁盘的过程类似,也有阀值和内存大小,阀值一样可以在配置文件里配置,而内存大小是直接使用reduce的tasktracker的内存大小,复制的时候reduce还会进行排序操作和合并文件操作,这些操作完毕之后就会进行reduce计算。
  5. reduce阶段: 和map函数一样,是编写好的reduce函数,最终结果是存储在hdfs上的。

参考文献:

[1] MapReduce编程模型的要点: http://blog.sina.com.cn/s/blog_4a1f59bf0100tgqj.html

[2] Hadoop权威指南(第三版)

[3] Hadoop应用开发技术详解

[4] mapreduce中reducers个数设置: http://www.2cto.com/os/201312/263998.html

[5] 操作系统典型调度算法: http://see.xidian.edu.cn/cpp/html/2595.html

[6] MapReduce框架结构: http://www.cppblog.com/javenstudio/articles/43073.html

[7] MapReduce框架详解: http://www.cnblogs.com/sharpxiajun/p/3151395.html


Hadoop分布式文件系统和I/O

一、Hadoop数据类型
Hadoop提供的数据类型,如下所示:

  1. BooleanWritable:标准布尔型数值
  2. ByteWritable:单字节数值
  3. DoubleWritable:双字节数
  4. FloatWritable:浮点数
  5. IntWritable:整型数
  6. LongWritable:长整型数
  7. Text:使用UTF8格式存储的文本
  8. NullWritable:当<key, value>中的key或value为空时使用

说明:

(1)这些数据类型都实现了WritableComparable接口,以便用这些类型定义的数据可以被序列化进行网络传输和文件存储,以及进行大小比较。

(2)对象序列化就是把一个对象变为二进制的数据流的一种方法,通过对象序列化可以方便地实现对象的传输和存储。


二、Hadoop文件的数据结构

       一般硬盘的存储系统是由盘片—>柱面—>磁道—>扇区,磁盘块(一个扇区大小)为512bytes,文件系统块(也叫数据块)为几千字节。这里要区分两个概念,即磁盘块和文件系统块,磁盘的最小存储单位是扇区(磁盘块),数据的最小存储单位是块(文件系统块)。构建于单个磁盘上的文件系统通过磁盘块来管理该文件系统块,该文件系统块的大小可以是磁盘块的整数倍。

       HDFS(Hadoop分布式文件系统)同样也有块(数据块或文件系统块)的概念,默认为64M,即磁盘进行数据读/写的最小单位,HDFS上的文件也被划分为块大小的多个分块,作为独立的存储单元。HDFS提供了两种类型的容器,一种是SequenceFile,一种是MapFile,两者均可以通过Hadoop API对其进行操作,也可以通过CLI(比如shell)对其进行操作,并且还可以将SequenceFile转换成为MapFile。

  • SequenceFile数据结构

SequenceFile主要由一个Header后跟多条Record组成,如下所示:


(1)Header主要包含了Key classname、Value classname存储压缩算法、用户自定义元数据等信息。此外,还包含了一些同步标识,用于快速定位到记录的边界。

(2)每条记录以键值对的方式进行存储,用来标示它的字符数组可依次解析成:记录的长度、Key的长度、Key值和Value值,并且Value值的结构取决于该记录是否被压缩。


说明:

(1)数据压缩的作用主要有两个,一是节省磁盘空间,一是加快网络传输,Sequence支持两种格式的数据压缩,分别是Record Compression和Block compression。前者是对每条记录的Value进行压缩。后者是将一连串的Record组织到一起,统一压缩成一个Block。

(2)Block信息主要存储:块所包含的记录数、每条记录Key长度的集合、每条记录Key值的集合、每条记录Value长度的集合和每条记录Value值的集合。

  • MapFile数据结构

       MapFile是排序后的SequenceFile,通过观察其目录结构可以看到MapFile由两部分组成,分别是data和index。index作为文件的数据索引,主要记录了每个Record的key值,以及该Record在文件中的偏移位置。在MapFile被访问的时候,索引文件会被加载到内存,通过索引映射关系可迅速定位到指定Record所在文件位置,因此,相对SequenceFile而言,MapFile的检索效率是高效的,缺点是会消耗一部分内存来存储index数据。
       需注意的是,MapFile并不会把所有Record都记录到index中去,默认情况下每隔128条记录存储一个索引映射。当然,记录间隔可人为修改,通过MapFIle.Writer的setIndexInterval()方法,或修改io.map.index.interval属性。

说明:

与SequenceFile不同的是,MapFile的KeyClass一定要实现WritableComparable接口,即Key值是可比较的。


三、Hadoop输入格式

InputFormat类的层次结构,如下所示:



四、Hadoop输出格式

OutputFormat类的层次结构,如下所示:



五、数据流

  • 文件读取剖析

客户端以及与之交互的HDFS、NameNode、DataNode的读数据流过程,如下所示:
  1. 客户端通过调用FileSyste对象的open()方法来打开希望读取的文件,对于HDFS来说,这个对象是分布式文件系统的一个实例。参见步骤1。
  2. DistributedFileSystem通过使用RPC来调用namenode,以确定文件起始块的位置。对于每一个块,namenode返回存有该块复本的datanode地址。此外,这些datanode根据它们与客户端的距离来排序。如果该客户端本身就是一个datanode(比如,在一个MapReduce任务中),并保存有相应数据块的一个复本时,该节点将从本地datanode中读取数据。参见步骤2。
  3. DistributedFileSystem类返回一个FSDataInputStream对象(一个支持文件定位的输入流)给客户端并读取数据。FSDataInputStream类转而封装DFSInputStream对象,该对象管理着datanode和namenode的I/O。接着,客户端对这个输入流调用read()方法。参见步骤3。
  4. 存储着文件起始块的datanode地址的DFSInputStream随即连接距离最近的datanode。通过对数据流反复调用read()方法,可以将数据从datanode传输到客户端。参见步骤4。
  5. 到达块的末端时,DFSInputStream会关闭与该datanode的连接,然后寻找下一个块的最佳datanode。客户端只需要读取连续的流,并且对于客户端都是透明的。参见步骤5。
  6. 客户端从流中读取数据时,块是按照打开DFSInputStream与datanode新建连接的顺序读取的。它也需要询问namenode来检索下一批所需块的datanode的位置。一旦客户端完成读取,就对FSDataInputStream调用close()方法。参见步骤6。
  • 文件写入剖析

客户端以及与之交互的HDFS、NameNode、DataNode的写数据流过程,如下所示:
  1. 客户端通过对DistributedFileSystem对象调用create()函数来创建文件。参见步骤1。
  2. DistributedFileSystem对namenode创建一个RPC调用,在文件系统的命名空间中创建一个新的文件,此时该文件中还没有相应的数据块。namenode执行各种不同的检查以确保这个文件不存在,并且客户端有创建该文件的权限。如果这些检查均通过,namenode就会为创建新文件记录一条记录;否则,文件创建失败并向客户端抛出一个IOException异常。参见步骤2。
  3. DistributedFileSystem向客户端返回一个FSDataOutputStream对象,由此客户端可以开始写入数据,就像读取事件一样,FSDataOutputStream封装一个DFSOutputStream对象,该对象负责处理datanode和namenode之间的通信。在客户端写入数据时,DFSOutputStream将它分成一个个的数据包,并写入内部队列,称为"数据队列"。
  4. DataStreamer处理数据队列,它的责任是根据datanode列表来要求namenode分配适合的新块来存储数据备份。这一组datanode构成一个管线——我们假设复本数为3,所以管线中有3个节点。DataStreamer将数据包流式传输到管线中第1个datanode,该datanode存储数据包并将它发送到管线中的第2个datanode。同样地,第2个datanode存储该数据包并且发送给管线中的第3个(也是最后一个)datanode。参见步骤4。
  5. DFSOutputStream也维护着一个内部数据包队列来等待datanode的收到确认回执,称为"确认队列"。当收到管道中所有datanode确认信息后,该数据包才会从确认队列删除。参数步骤5。
  6. 客户端完成数据的写入后,会对数据流调用close()方法。参见步骤6。该操作将剩余的所有数据包写入datanode管线中,并在联系namenode且发送文件写入完成信息之前,等待确认。参见步骤7。namenode已经知道文件由哪些块组成(通过DataStreamer询问数据块的分配),所以它在返回成功前只需要等待数据块进行最小量的复制。

参考文献:

[1] Hadoop权威指南

[2] Hadoop应用开发技术详解

[3] Java开发实战经典



  •                     <li class="tool-item tool-active is-like "><a href="javascript:;"><svg class="icon" aria-hidden="true">
                            <use xlink:href="#csdnc-thumbsup"></use>
                        </svg><span class="name">点赞</span>
                        <span class="count"></span>
                        </a></li>
                        <li class="tool-item tool-active is-collection "><a href="javascript:;" data-report-click="{&quot;mod&quot;:&quot;popu_824&quot;}"><svg class="icon" aria-hidden="true">
                            <use xlink:href="#icon-csdnc-Collection-G"></use>
                        </svg><span class="name">收藏</span></a></li>
                        <li class="tool-item tool-active is-share"><a href="javascript:;" data-report-click="{&quot;mod&quot;:&quot;1582594662_002&quot;}"><svg class="icon" aria-hidden="true">
                            <use xlink:href="#icon-csdnc-fenxiang"></use>
                        </svg>分享</a></li>
                        <!--打赏开始-->
                                                <!--打赏结束-->
                                                <li class="tool-item tool-more">
                            <a>
                            <svg t="1575545411852" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="5717" xmlns:xlink="http://www.w3.org/1999/xlink" width="200" height="200"><defs><style type="text/css"></style></defs><path d="M179.176 499.222m-113.245 0a113.245 113.245 0 1 0 226.49 0 113.245 113.245 0 1 0-226.49 0Z" p-id="5718"></path><path d="M509.684 499.222m-113.245 0a113.245 113.245 0 1 0 226.49 0 113.245 113.245 0 1 0-226.49 0Z" p-id="5719"></path><path d="M846.175 499.222m-113.245 0a113.245 113.245 0 1 0 226.49 0 113.245 113.245 0 1 0-226.49 0Z" p-id="5720"></path></svg>
                            </a>
                            <ul class="more-box">
                                <li class="item"><a class="article-report">文章举报</a></li>
                            </ul>
                        </li>
                                            </ul>
                </div>
                            </div>
            <div class="person-messagebox">
                <div class="left-message"><a href="https://blog.csdn.net/zkl99999">
                    <img src="https://profile.csdnimg.cn/1/E/3/3_zkl99999" class="avatar_pic" username="zkl99999">
                                            <img src="https://g.csdnimg.cn/static/user-reg-year/2x/6.png" class="user-years">
                                    </a></div>
                <div class="middle-message">
                                        <div class="title"><span class="tit"><a href="https://blog.csdn.net/zkl99999" data-report-click="{&quot;mod&quot;:&quot;popu_379&quot;}" target="_blank">learn deep learning</a></span>
                                            </div>
                    <div class="text"><span>发布了32 篇原创文章</span> · <span>获赞 232</span> · <span>访问量 139万+</span></div>
                </div>
                                <div class="right-message">
                                            <a href="https://bbs.csdn.net/topics/395529955" target="_blank" class="btn btn-sm btn-red-hollow bt-button personal-messageboard">他的留言板
                        </a>
                                                            <a class="btn btn-sm  bt-button personal-watch" data-report-click="{&quot;mod&quot;:&quot;popu_379&quot;}">关注</a>
                                    </div>
                            </div>
                    </div>
    
  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
《大规模分布式存储系统:原理解析与架构实战》是分布式系统领域的经典著作,由阿里巴巴高级技术专家“阿里日照”(OceanBase核心开发人员)撰写,阳振坤、章文嵩、杨卫华、汪源、余锋(褚霸)、赖春波等来自阿里、新浪、网易和百度的资深技术专家联袂推荐。理论方面,不仅讲解了大规模分布式存储系统的核心技术和基本原理,而且对谷歌、亚马逊、微软和阿里巴巴等国际型大互联网公司的大规模分布式存储系统进行了分析;实战方面,首先通过对阿里巴巴的分布式数据库OceanBase的实现细节的深入剖析完整地展示了大规模分布式存储系统的架构与设计过程,然后讲解了大规模分布式存储技术在云计算和大数据领域的实践与应用。, 《大规模分布式存储系统:原理解析与架构实战》内容分为四个部分:基础篇——分布式存储系统的基础知识,包含单机存储系统的知识,如数据模型、事务与并发控制、故障恢复、存储引擎、压缩/解压缩等;分布式系统的数据分布、复制、一致性、容错、可扩展性等。范型篇——介绍谷歌、亚马逊、微软、阿里巴巴等著名互联网公司的大规模分布式存储系统架构,涉及分布式文件系统、分布式键值系统、分布式表格系统以及分布式数据库技术等。实践篇——以阿里巴巴的分布式数据库OceanBase为例,详细介绍分布式数据库内部实现,以及实践过程中的经验。专题篇——介绍分布式系统的主要应用:云存储和大数据,这些是近年来的热门领域,本书介绍了云存储平台、技术与安全,以及大数据的概念、流式计算、实时分析等。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值