Hadoop生态系统介绍及HDFS与MapReduce原理详细阐述

1、Hadoop生态系统概况

Hadoop是一个能够对大量数据进行分布式处理的软件框架。具有 可靠、高效、可伸缩的特点。
Hadoop的核心是HDFS和Mapreduce,hadoop2.0还包括YARN。
下图为hadoop的生态系统:

2、HDFS(Hadoop分布式文件系统)

源自于Google的GFS论文,发表于2003年10月,HDFS是GFS克隆版。
是Hadoop体系中 数据存储管理的基础。它是一个高度容错的系统,能检测和应对硬件故障,用于在低成本的通用硬件上运行。HDFS简化了文件的一致性模型,通过流式数据访问,提供高吞吐量应用程序数据访问功能,适合带有大型数据集的应用程序。

Client切分文件;访问HDFS;与NameNode交互,获取文件位置信息;与DataNode交互,读取和写入数据
NameNode:Master节点,在hadoop1.X中只有一个,管理HDFS的名称空间和数据块映射信息,配置副本策略,处理客户端请求。
DataNode:Slave节点,存储实际的数据,汇报存储信息给NameNode。
Secondary NameNode:辅助NameNode,分担其工作量;定期合并fsimage和fsedits,推送给NameNode;紧急情况下,可辅助恢复NameNode,但Secondary NameNode并非NameNode的热备。

3、Mapreduce(分布式计算框架)

源自于google的MapReduce论文,发表于2004年12月,Hadoop MapReduce是google MapReduce 克隆版。
源自于google的MapReduce论文
MapReduce是一种 计算模型,用以进行大数据量的计算。其中Map对数据集上的独立元素进行指定的操作,生成键-值对形式中间结果。Reduce则对中间结果中相同“键”的所有“值”进行规约,以得到最终结果。MapReduce这样的功能划分,非常适合在大量计算机组成的分布式并行环境里进行数据处理。

JobTracker:Master节点,只有一个,管理所有作业,作业/任务的监控、错误处理等;将任务分解成一系列任务,并分派给TaskTracker。
TaskTracker:Slave节点,运行Map Task和Reduce Task;并与JobTracker交互,汇报任务状态。
Map Task:解析每条数据记录,传递给用户编写的map(),并执行,将输出结果写入本地磁盘(如果为map-only作业,直接写入HDFS)。
Reducer Task:从Map Task的执行结果中,远程读取输入数据,对数据进行排序,将数据按照分组传递给用户编写的reduce函数执行。
Mapreduce处理流程,以wordCount为例:

4、Hive(基于Hadoop的数据仓库)

由facebook开源,最初用于解决海量结构化的日志数据统计问题。
Hive定义了一种类似SQL的查询语言( HQL), 将SQL转化为MapReduce任务在Hadoop上执行
通常用于 离线分析。

5、Hbase(分布式列存数据库)

源自Google的Bigtable论文,发表于2006年11月,HBase是Google Bigtable克隆版
HBase是一个针对结构化数据的 可伸缩、高可靠、高性能、分布式和面向列的动态模式数据库。和传统关系数据库不同,HBase采用了BigTable的数据模型:增强的稀疏排序映射表(Key/Value),其中,键由行关键字、列关键字和时间戳构成。HBase提供了对大规模数据的随机、实时读写访问,同时,HBase中保存的数据可以使用MapReduce来处理,它将数据存储和并行计算完美地结合在一起。
数据模型:Schema-->Table-->Column Family-->Column-->RowKey-->TimeStamp-->Value

6、Zookeeper(分布式协作服务)

源自Google的Chubby论文,发表于2006年11月,Zookeeper是Chubby克隆版
解决分布式环境下的数据管理问题: 统一命名,状态同步,集群管理,配置同步等

7、Sqoop(数据同步工具)

Sqoop是SQL-to-Hadoop的缩写,主要用于 传统数据库和Hadoop之前传输数据
数据的导入和导出 本质上是Mapreduce程序,充分利用了MR的并行化和容错性。

8、Pig(基于Hadoop的数据流系统)

由yahoo!开源,设计动机是提供一种基于MapReduce的ad-hoc(计算在query时发生)数据分析工具
定义了一种数据流语言—Pig Latin,将脚本转换为MapReduce任务在Hadoop上执行。
通常用于进行离线分析。

9、Mahout(数据挖掘算法库)

Mahout起源于2008年,最初是Apache Lucent的子项目,它在极短的时间内取得了长足的发展,现在是Apache的顶级项目。
Mahout的主要目标是创建一些可扩展的机器学习领域经典算法的实现,旨在帮助开发人员更加方便快捷地创建智能应用程序。Mahout现在已经包含了聚类、分类、推荐引擎(协同过滤)和频繁集挖掘等广泛使用的数据挖掘方法。除了算法,Mahout还包含数据的输入/输出工具、与其他存储系统(如数据库、MongoDB 或Cassandra)集成等数据挖掘支持架构。

10、Flume(日志收集工具)

Cloudera开源的日志收集系统,具有分布式、高可靠、高容错、易于定制和扩展的特点。
它将数据从产生、传输、处理并最终写入目标的路径的过程抽象为数据流,在具体的数据流中,数据源支持在Flume中定制数据发送方,从而支持收集各种不同协议数据。同时,Flume数据流提供对日志数据进行简单处理的能力,如过滤、格式转换等。此外,Flume还具有能够将日志写往各种数据目标(可定制)的能力。总的来说,Flume是一个可扩展、适合复杂环境的海量日志收集系统。

HDFS原理详解:

  • 产生背景

以文件为基本存储单位的缺点
1、文件大小不同,难以实现负载均衡。
2、处理一个文件时,只能利用一个节点资源,无法动用集群。

  • HFDS的定义

源自于Google的GFS论文
    发表于2003年10月
    HDFS是GFS克隆版
Hadoop Distributed File System
    易于扩展的分布式文件系统
    运行在大量普通廉价机器上,提供容错机制
    为大量用户提供性能不错的文件存取服务
  • HDFS的优缺点
优点
1)高容错性
    数据自动保存多个副本
    副本丢失后,自动恢复
2)适合批处理
    移动计算而非数据
    数据位置暴露给计算框架
3)适合大数据处理
    GB、TB、甚至PB级数据
    百万规模以上的文件数量
    10K+节点规模
4)流式文件访问
    一次性写入,多次读取
    保证数据一致性
5)可构建在廉价机器上
    通过多副本提高可靠性
    提供了容错和恢复机制
不擅长:
1)低延迟与高吞吐率的数据访问 ,比如毫秒级
2)小文件存取
    占用NameNode大量内存 
    寻道时间超过读取时间 
3)并发写入、文件随机修改
    一个文件同一个时间只能有一个写者
    仅支持append

  • HDFS架构




Client:切分文件;访问或通过命令行管理HDFS;与NameNode交互,获取文件位置信息;与DataNode交互,读取和写入数据。
NameNode:Master节点,只有一个,管理HDFS的名称空间和数据块映射信息;配置副本策略;处理客户端请求。
DataNode:Slave节点,存储实际的数据;执行数据块的读写;汇报存储信息给NameNode。
Secondary NameNode:辅助NameNode,分担其工作量;定期合并fsimage和fsedits,推送给NameNode;紧急情况下,可辅助恢复NameNode,但Secondary NameNode并非NameNode的热备。
fsimage和fsedits
NameNode中两个很重要的文件,
fsimage是元数据镜像文件(保存文件系统的目录树)。
edits是元数据操作日志(记录每次保存fsimage之后到下次保存之间的所有hdfs操作)。
内存中保存了最新的元数据信息(fsimage和edits)。
edits过大会导致NameNode重启速度慢,Secondary NameNode负责定期合并它们。

合并的流程图:
数据块的映射关系
1)包括两种:文件与数据块映射关系,DataNode与数据块映射关系;
2)NameNode启动的时候,可通过心跳信息重构映射信息,DataNode运行过程中定时汇报当前block信息;映射关系保存在NameNode内存中。
3)NameNode重启速度慢(需要加载通过合并fsimage与edits文件生成的最新目录树以及DataNode的块信息)
数据块(block)
1)在HDFS中,文件被切分成固定大小的数据块,默认大小为64MB,也可自己配置。
2)为何数据块如此大,因为数据传输时间超过寻道时间(高吞吐率)。
3)文件的存储方式:按大小被切分成若干个block,存储到不同节点上,默认情况下每个block有三个副本。
对于block块的恢复详细信息可以查看如下blog
http://blog.csdn.net/macyang/article/details/7983188
HDFS的默认副本存放策略
Hadoop 0.17 之后:副本1-同Client的节点上;副本2-不同机架中的节点上;副本3-同第二个副本的机架中的另一个节点上;其他副本:随机挑选。如下图示例:


  • HDFS可靠性机制

常见错误情况:文件损坏;网络或者机器失效;NameNode挂掉;
文件的完整性:通过CRC32校验,如果有损坏,用其他副本替代损坏文件;
Heartbeat:DataNode定期向NameNode发送eartbeat;
元数据信息:FsImage、Editlog进行多份备份,当NameNode宕机后,可手动还原。


  • HDFS物理网络环境


  • HDFD的读写流程

这个网站很详细很好:http://bradhedlund.com/2011/09/10/understanding-hadoop-clusters-and-the-network/

HDFS文件读取:


1.首先调用FileSystem对象的open方法,其实是一个DistributedFileSystem的实例
2.DistributedFileSystem通过rpc获得文件的第一批个block的locations,同一block按照重复数会返回多个locations,这些locations按照hadoop拓扑结构排序,距离客户端近的排在前面.
3.前两步会返回一个FSDataInputStream对象,该对象会被封装成DFSInputStream对象,DFSInputStream可以方便的管理datanode和namenode数据流。客户端调用read方法,DFSInputStream最会找出离客户端最近的datanode并连接。
4.数据从datanode源源不断的流向客户端。
5.如果第一块的数据读完了,就会关闭指向第一块的datanode连接,接着读取下一块。这些操作对客户端来说是透明的,客户端的角度看来只是读一个持续不断的流。
6.如果第一批block都读完了,DFSInputStream就会去namenode拿下一批blocks的location,然后继续读,如果所有的块都读完,这时就会关闭掉所有的流。

HDFS读取发生异常处理
       如果在读数据的时候,DFSInputStream和datanode的通讯发生异常,就会尝试正在读的block的排第二近的datanode,并且会记录哪个datanode发生错误,剩余的blocks读的时候就会直接跳过该datanode。DFSInputStream也会检查block数据校验和,如果发现一个坏的block,就会先报告到namenode节点,然后DFSInputStream在其他的datanode上读该block的镜像
HDFS读操作设计思考
       客户端直接连接datanode来检索数据并且namenode来负责为每一个block提供最优的datanode,namenode仅仅处理block location的请求,这些信息都加载在namenode的内存中,hdfs通过datanode集群可以承受大量客户端的并发访问。

HDFS文件写入

1.客户端通过调用DistributedFileSystem的create方法创建新文件
2.DistributedFileSystem通过RPC调用namenode去创建一个没有blocks关联的新文件,创建前,namenode会做各种校验,比如文件是否存在,客户端有无权限去创建等。如果校验通过,namenode就会记录下新文件,否则就会抛出IO异常.
3.前两步结束后会返回FSDataOutputStream的对象,和读文件的时候相似,FSDataOutputStream被封装成DFSOutputStream,DFSOutputStream可以协调namenode和datanode。客户端开始写数据到DFSOutputStream,DFSOutputStream会把数据切成一个个小packet,然后排成队列data quene。
4.DataStreamer会去处理接受data quene,他先问询namenode这个新的block最适合存储的在哪几个datanode里,比如重复数是3,那么就找到3个最适合的datanode,把他们排成一个pipeline.DataStreamer把packet按队列输出到管道的第一个datanode中,第一个datanode又把packet输出到第二个datanode中,以此类推。
5.DFSOutputStream还有一个对列叫ack quene,也是有packet组成,等待datanode的收到响应,当pipeline中的所有datanode都表示已经收到的时候,这时akc quene才会把对应的packet包移除掉。
6.客户端完成写数据后调用close方法关闭写入流
7.DataStreamer把剩余得包都刷到pipeline里然后等待ack信息,收到最后一个ack后,通知datanode把文件标示为已完成。
HDFS文件写入失败
       如果在写的过程中某个datanode发生错误,会采取以下几步:
       1.pipeline被关闭
       2.为了防止防止丢包ack quene里的packet会同步到data quene
       3.把产生错误的datanode上当前在写但未完成的block删
       4.block剩下的部分被写到剩下的两个正常的datanode
       5.namenode找到另外的datanode去创建这个块的复
       这些操作对客户端来说是无感知的。
       (客户端执行write操作后,写完得block才是可见的,正在写的block对客户端是不可见的,只有调用sync方法,客户端才确保该文件被写操作已经全部完成,当客户端调用close方法时会默认调用sync方法。是否需要手动调用取决你根据程序需要在数据健壮性和吞吐率之间的权衡。)

注:此部分笔记来源于:http://bbs.chinahadoop.cn/forum.php?mod=viewthread&tid=5673&fromuid=696

  • HDFS与其他系统的结合

1)HDFS与MapReduce结合
MapReduce作业的输入数据来自HDFS,最终结果也写入HDFS
Mapreduce和HDFS是低耦合的,Mapreduce可以与其他分布式系统结合。HDFS之上可以是其他框架。
2)HDFS与Hbase结合
HDFS为Hbase提供可靠的数据存放服务(操作日志文件WAL和数据索引文件HFile等)

MapReduce原理详解

1.MapReduce作业运行流程

下面贴出我用visio2010画出的流程示意图:

流程分析:

1.在客户端启动一个作业。

2.向JobTracker请求一个Job ID。

3.将运行作业所需要的资源文件复制到HDFS上,包括MapReduce程序打包的JAR文件、配置文件和客户端计算所得的输入划分信息。这些文件都存放在JobTracker专门为该作业创建的文件夹中。文件夹名为该作业的Job ID。JAR文件默认会有10个副本(mapred.submit.replication属性控制);输入划分信息告诉了JobTracker应该为这个作业启动多少个map任务等信息。

4.JobTracker接收到作业后,将其放在一个作业队列里,等待作业调度器对其进行调度(这里是不是很像微机中的进程调度呢,呵呵),当作业调度器根据自己的调度算法调度到该作业时,会根据输入划分信息为每个划分创建一个map任务,并将map任务分配给TaskTracker执行。对于map和reduce任务,TaskTracker根据主机核的数量和内存的大小有固定数量的map槽和reduce槽。这里需要强调的是:map任务不是随随便便地分配给某个TaskTracker的,这里有个概念叫:数据本地化(Data-Local)。意思是:将map任务分配给含有该map处理的数据块的TaskTracker上,同时将程序JAR包复制到该TaskTracker上来运行,这叫“运算移动,数据不移动”。而分配reduce任务时并不考虑数据本地化。

5.TaskTracker每隔一段时间会给JobTracker发送一个心跳,告诉JobTracker它依然在运行,同时心跳中还携带着很多的信息,比如当前map任务完成的进度等信息。当JobTracker收到作业的最后一个任务完成信息时,便把该作业设置成“成功”。当JobClient查询状态时,它将得知任务已完成,便显示一条消息给用户。
以上是在客户端、JobTracker、TaskTracker的层次来分析MapReduce的工作原理的,下面我们再细致一点,从map任务和reduce任务的层次来分析分析吧。

2.Map、Reduce任务中Shuffle和排序的过程

同样贴出我在visio中画出的流程示意图:

流程分析:

Map端:

1.每个输入分片会让一个map任务来处理,默认情况下,以HDFS的一个块的大小(默认为64M)为一个分片,当然我们也可以设置块的大小。map输出的结果会暂且放在一个环形内存缓冲区中(该缓冲区的大小默认为100M,由io.sort.mb属性控制),当该缓冲区快要溢出时(默认为缓冲区大小的80%,由io.sort.spill.percent属性控制),会在本地文件系统中创建一个溢出文件,将该缓冲区中的数据写入这个文件。

2.在写入磁盘之前,线程首先根据reduce任务的数目将数据划分为相同数目的分区,也就是一个reduce任务对应一个分区的数据。这样做是为了避免有些reduce任务分配到大量数据,而有些reduce任务却分到很少数据,甚至没有分到数据的尴尬局面。其实分区就是对数据进行hash的过程。然后对每个分区中的数据进行排序,如果此时设置了Combiner,将排序后的结果进行Combia操作,这样做的目的是让尽可能少的数据写入到磁盘。

3.当map任务输出最后一个记录时,可能会有很多的溢出文件,这时需要将这些文件合并。合并的过程中会不断地进行排序和combia操作,目的有两个:1.尽量减少每次写入磁盘的数据量;2.尽量减少下一复制阶段网络传输的数据量。最后合并成了一个已分区且已排序的文件。为了减少网络传输的数据量,这里可以将数据压缩,只要将mapred.compress.map.out设置为true就可以了。

4.将分区中的数据拷贝给相对应的reduce任务。有人可能会问:分区中的数据怎么知道它对应的reduce是哪个呢?其实map任务一直和其父TaskTracker保持联系,而TaskTracker又一直和JobTracker保持心跳。所以JobTracker中保存了整个集群中的宏观信息。只要reduce任务向JobTracker获取对应的map输出位置就ok了哦。

到这里,map端就分析完了。那到底什么是Shuffle呢?Shuffle的中文意思是“洗牌”,如果我们这样看:一个map产生的数据,结果通过hash过程分区却分配给了不同的reduce任务,是不是一个对数据洗牌的过程呢?呵呵。

Reduce端:
1.Reduce会接收到不同map任务传来的数据,并且每个map传来的数据都是有序的。如果reduce端接受的数据量相当小,则直接存储在内存中(缓冲区大小由mapred.job.shuffle.input.buffer.percent属性控制,表示用作此用途的堆空间的百分比),如果数据量超过了该缓冲区大小的一定比例(由mapred.job.shuffle.merge.percent决定),则对数据合并后溢写到磁盘中。

2.随着溢写文件的增多,后台线程会将它们合并成一个更大的有序的文件,这样做是为了给后面的合并节省时间。其实不管在map端还是reduce端,MapReduce都是反复地执行排序,合并操作,现在终于明白了有些人为什么会说:排序是hadoop的灵魂。

3.合并的过程中会产生许多的中间文件(写入磁盘了),但MapReduce会让写入磁盘的数据尽可能地少,并且最后一次合并的结果并没有写入磁盘,而是直接输入到reduce函数。

  • 1
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值