Hadoop底层原理图

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/zimiao552147572/article/details/88880493

大数据组件使用 总文章

node-01节点:NameNode  DataNode    ResourceManager 
node-02节点:DataNode  NodeManager    SecondaryNameNode 
node-03节点:DataNode  NodeManager


1.仍需继续增加机器的话,只需要继续增加“node-03节点”一样的机器即可
2.HDFS 集群中:Namenode 是 HDFS 集群主节点,Datanode 是 HDFS 集群从节点,SecondaryNameNode 是主节点NameNode的备份  
3.YARN 集群中:ResourceManager 是 YARN 集群主节点,NodeManager 是 YARN 集群从节点

HDFS 基本操作 
    推荐 命令格式一:hadoop fs 参数
    命令格式二:hdfs dfs 参数

1.分块存储:HDFS 中的文件在物理上是分块存储(block)的,块的大小可以通过配置参数来规定,默认大小在 hadoop2.x 版本中是 128M。
2.Namenode 元数据管理 
    我们把目录结构及文件分块位置信息叫做元数据。Namenode 负责维护整个 hdfs 文件系统的目录树结构,
    以及每一个文件所对应的 block 块信息(block 的id,及所在的 datanode 服务器,Datanode 是 HDFS 集群从节点) 。
3.Datanode 数据存储 
    文件的各个 block 的具体存储管理由 datanode 节点承担。每一个 block 都可以在多个 datanode 上。
     Datanode 需要定时向 Namenode 汇报自己持有的 block信息。 
    存储多个副本(副本数量也可以通过参数设置 dfs.replication,默认是 3)
4.副本机制 
    为了容错,文件的所有 block 都会有副本。每个文件的 block 大小和副本系数都是可配置的。
    应用程序可以指定某个文件的副本数目。副本系数可以在文件创建的时候指定,也可以在之后改变。
5.一次写入,多次读出 
    HDFS 是设计成适应一次写入,多次读出的场景,且不支持文件的修改。 
    正因为如此,HDFS 适合用来做大数据分析的底层存储服务,并不适合用来做网盘等应用,
    因为,修改不方便,延迟大,网络开销大,成本太高。
 

================== Secondary NameNode============== 

1.在Hadoop中,有一些命名不好的模块,Secondary NameNode是其中之一。
  从它的名字上看,它给人的感觉就像是NameNode的备份。但它实际上却不是。
2.NameNode
    NameNode主要是用来保存HDFS的元数据信息,比如命名空间信息,块信息等。
    当它运行的时候,这些信息是存在内存中的。但是这些信息也可以持久化到磁盘上。

    上面的这张图片展示了NameNode怎么把元数据保存到磁盘上的。这里有两个不同的文件:
        1.fsimage - 它是在NameNode启动时对整个文件系统的快照
        2.edit logs - 它是在NameNode启动后,对文件系统的改动序列

    只有在NameNode重启时,edit logs才会合并到fsimage文件中,从而得到一个文件系统的最新快照。
    但是在产品集群中NameNode是很少重启的,这也意味着当NameNode运行了很长时间后,edit logs文件会变得很大。
    在这种情况下就会出现下面一些问题:
        edit logs文件会变的很大,怎么去管理这个文件是一个挑战。
        NameNode的重启会花费很长时间,因为有很多在edit logs中的改动 要合并到fsimage文件上。
        如果NameNode挂掉了,那我们就丢失了很多改动因为此时的fsimage文件非常旧。
        笔者认为在这个情况下丢失的改动不会很多, 因为丢失的改动应该是还在内存中但是没有写到edit logs的这部分。

    因此为了克服这个问题,我们需要一个易于管理的机制来帮助我们减小edit logs文件的大小和得到一个最新的fsimage文件,
    这样也会减小在NameNode上的压力。这跟Windows的恢复点是非常像的,Windows的恢复点机制允许我们对OS进行快照,
    这样当系统发生问题时,我们能够回滚到最新的一次恢复点上。
    现在我们明白了NameNode的功能和所面临的挑战 - 保持文件系统最新的元数据。
    那么,这些跟Secondary NameNode又有什么关系呢?

3.Secondary NameNode
    SecondaryNameNode就是来帮助解决上述问题的,它的职责是合并NameNode的 edit logs 到 fsimage文件中。

    上面的图片展示了Secondary NameNode是怎么工作的。
        1.首先,它定时到NameNode去获取edit logs,并更新到Secondary NameNode自己的fsimage上 
        2.一旦它有了新的fsimage文件,它将其拷贝回NameNode中。
        3.NameNode在下次重启时会使用这个新的fsimage文件,从而减少重启的时间。

    Secondary NameNode的整个目的是在HDFS中提供一个检查点。
    它只是NameNode的一个助手节点。这也是它在社区内被认为是检查点节点的原因。
    现在,我们明白了Secondary NameNode所做的不过是在文件系统中设置一个检查点来帮助NameNode更好的工作。
    它不是要取代掉NameNode也不是NameNode的备份。所以从现在起,让我们养成一个习惯,称呼它为检查点节点吧。

    关于NameNode是什么时候将改动写到edit logs中的?这个操作实际上是由DataNode的写操作触发的,
    当我们往DataNode写文件时,DataNode会跟NameNode通信,告诉NameNode什么文件的第几个block放在它那里,
    NameNode这个时候会将这些元数据信息写到edit logs文件中。

4.Secondarynamenode作用
    SecondaryNameNode有两个作用,一是镜像备份,二是日志与镜像的定期合并。
    两个过程同时进行,称为checkpoint.
    镜像备份的作用:备份fsimage(fsimage是元数据发送检查点时写入文件);
    日志与镜像的定期合并的作用:
        将Namenode中edits日志和fsimage合并,防止如果Namenode节点故障,
        namenode下次启动的时候,会把fsimage加载到内存中,应用edit log,edit log往往很大,导致操作往往很耗时。

    Secondarynamenode工作原理
    日志与镜像的定期合并总共分五步:
        1.SecondaryNameNode通知NameNode准备提交edits文件,此时主节点产生edits.new
        2.SecondaryNameNode通过http get方式获取NameNode的fsimage与edits文件
         (在SecondaryNameNode的current同级目录下可见到 temp.check-point或者previous-checkpoint目录,
           这些目录中存储着从namenode拷贝来的镜像文件)
        3.SecondaryNameNode开始合并获取的上述两个文件,产生一个新的fsimage文件fsimage.ckpt
        4.SecondaryNameNode用http post方式发送fsimage.ckpt至NameNode
        5.NameNode将fsimage.ckpt与edits.new文件分别重命名为fsimage与edits,然后更新fstime,
          整个checkpoint过程到此结束。

    在新版本的hadoop中(hadoop0.21.0),SecondaryNameNode两个作用被两个节点替换, 
    checkpoint node与backup node. SecondaryNameNode备份由三个参数控制fs.checkpoint.period控制周期,
    fs.checkpoint.size控制日志文件超过多少大小时合并, dfs.http.address表示http地址,
    这个参数在SecondaryNameNode为单独节点时需要设置。
 

================================================

1.客户端执行hadoop fs -get hdfs文件系统中的文件路径 本地文件系统中的目录路径:hadoop fs -get /a.txt /root/ 
  客户端发送请求给namenode,请求获取文件
2.namenode根据客户端所请求下载的文件路径,到hdfs文件系统中找到对应的文件是否存在,存在则返回该文件对应的每个文件块所存储在的每个datanode的IP地址信息,
  和 同时包括返回该datanode中保存的对应该文件的所有的每个文件块,每个datanode的IP地址信息按照离客户端的距离远近进行排序插入到一个列表中,
  距离客户端近的datanode则把他的IP地址信息插在前面。
3.客户端则根据每个datanode的IP地址信息到对应的datanode中取出对应该文件的所有的每个文件块,最终进行合并校验完整。

1.客户端执行hdfs fs put 本地文件系统中的文件路径 hdfs文件系统中的目录路径:hdfs fs put ./a.txt / 发送上传请求给namenode。
2.namenode根据元数据中的文件系统目录树 检测是否存在“该指定的接收上传文件的”目录,检测成功则返回成功信息给客户端。
3.客户端根据上传文件被分为多少份文件块,向namenode请求获取对应多少个datanode,每个datanode负责接收一份文件块。
4.namenode根据元数据中的datanode信息池 检测出可用的N台datanode,每个datanode负责接收一份文件块,namenode把可用的N台datanode的IP地址信息返回给客户端,
  每台datanode根据所离客户端的距离远近进行排序插入到一个列表中,离客户端距离最近的datanode排在最前面,比如顺序是 datanode1、datanode2、datanode3。
5.客户端根据离自己最近的datanode逐一建立pipeline管道连接,客户端 和 每个datanode 建立成一条 pipeline管道链接是:客户端 --> datanode1 --> datanode2 --> datanode3。
6.客户端每发送完一个文件块,其所存储该文件块的某个datanode就会返回 ack(命令正确应答)给客户端。
    1.客户端给某个datanode发送文件块时,按照在建立好的 pipeline管道链接中查找对应保存该文件块的datanode,
      逐级把文件块从一个datanode传输到另外一个databode,最终保存到指定保存该文件块的datanode中。
    2.当某个datanode保存完一个文件块后,该datanode返回 ack(命令正确应答),并按照建立好的 pipeline管道链接进行 原路返回ack(命令正确应答)给客户端,
      客户端才会继续发送下一个文件块。
7.所有datanode保存完所有的文件块并数据校验完整之后,返回成功信息给客户端

1.Reduce阶段 默认只有一个ReduceTask,那么Reduce阶段只输出一个文件
2.job.setNumReduceTasks(N):设置ReduceTask的个数,那么Reduce阶段输出的文件个数也为N,和ReduceTask的个数相同
3.Map阶段的多个MapTask各自输出的<key,value>根据“key.hashcode % ReduceTask个数”的规则,决定把<key,value>输出到哪个ReduceTask中,那么也即存储在哪个输出文件中。
  根据“key.hashcode % ReduceTask个数”规则所展现的效果显示: 相同key的 <key,value>都会被分配到同一个ReduceTask中,并且在同一个输出文件中。
4.切片大小默认等于块大小,即对文件以128M为一个block块进行切分,切片个数决定了MR程序启动多少个MapTask。

5.Map阶段(MapTask):map(起始偏移量key, 这一行内容value, Context context){ context.write(new Text(单词),new IntWritable(1)); # <单词,1> }
    1.第一步:write到内存缓冲区,直到溢出后存储到磁盘中(带有IO)。
         并且根据 “job.setNumReduceTasks(N)所设置ReduceTask个数的”规则 在磁盘中 产生相同的分区数,分区规则同为“key.hashcode % ReduceTask个数”,
         把相同key的 <key,value>都分配到同一个磁盘中的分区中,然后按照key的字典序对多个<key,value>进行排序。
         并且磁盘中每个分区各自对应一个ReduceTask,比如磁盘中第一个分区对应第一个ReduceTask,如此类推。
    2.第二步:磁盘中每个分区各自把<key,value>输出到对应的ReduceTask,比如磁盘中第一个分区输出数据到第一个ReduceTask,如此类推。

6.Reduce阶段(ReduceTask):reduce(单词keyIn, Iterable [1,1,...], Context context){ context.write(单词,总数); # <单词,总数> }
    1.第一步:ReduceTask把磁盘分区中送过来的数据按照key的字典序对多个<key,value>进行排序,然后把key相同的作为一组汇总成 <单词,[1,1,...]>,
         并调用reduce函数进行统计汇总单词的总次数
    2.第二步:ReduceTask把<单词,总数>输出到hdfs中的文件中

猜你喜欢

转载自blog.csdn.net/zimiao552147572/article/details/88880493