HDFS+MapReduce(超级详细)

问:分布式文件系统这么多,为什么Hadoop还要开发hdfs?
答:更好的实现分布式计算

部分内容整理自
Hadoop-MapReduce原理精讲、轻松入门
【史上最全】Hadoop 核心 - HDFS 分布式文件系统详解(上万字建议收藏)强推!!!
MapReduce高级应用——全排序和二次排序
MapReduce工作流程最详细解释

HDFS

  1. 数据移动的成本很高,所以将计算向数据移动
  2. 主从式结构,只设置一个主节点,因为保持数据一致性比较麻烦
  3. 在现代的企业环境中,单机容量往往无法存储大量数据,需要跨机器存储。统一管理分布在集群上的文件系统称为分布式文件系统。
  4. HDFS 使用多台计算机存储文件,并且提供统一的访问接口,像是访问一个普通文件系统一样使用分布式文件系统。

在这里插入图片描述

  • 理解偏移量offset:8个字节文件,块为4个字节。那第一个块的偏移量为0,第二个块偏移量为4
  • 同一个文件的块大小都一样,除非最后一个块,因为可能文件剩余不足。但不同文件的块可以不一样
  • 块的副本有几块,是包括它自己的,因为都处于同一地位。放在不同的节点上,可以解决可靠性和性能的问题。性能体现在多副本块可以同时进行计算。
  • 一次写入,多次读取,不支持修改。因为块的容量是固定的,如果修改一个块,那会造成之后的块的数据都会改变。
    在这里插入图片描述

架构设计

主从结构(主节点和从结点协调工作)

在这里插入图片描述

hdfs维护一个目录树结构,类似linux文件系统
在这里插入图片描述

NameNode&&DataNode

HDFS是一个主/从(Mater/Slave)体系结构,由三部分组成:NameNode 和 DataNode 以及SecondaryNamenode:

  • NameNode 负责管理整个文件系统的元数据,以及每一个路径(文件)所对应的数据块信息。

  • DataNode 负责管理用户的文件数据块,每一个数据块都可以在多个 DataNode 上存储多个副本,默认为3个。

  • Secondary NameNode 用来监控 HDFS 状态的辅助后台程序,每隔一段时间获取 HDFS 元数据的快照。最主要作用是辅助NameNode 管理元数据信息。
    在这里插入图片描述
    part-0文件有两个部分
    part-1文件有三个部分
    在这里插入图片描述
    NameNode

  • 完全基于内存存储文件元数据,目录结构,文件block的映射(因为内存块)

  • 需要持久化方案保证数据可靠性(内存不可靠并且有大小限制)

  • 提供副本放置策略

DataNode

  • 基于本地磁盘存储block(文件的形式)
  • 并保存block的校验和数据保证block的可靠性
  • 与NameNode保持心跳,汇报block列表状态

数据持久化

  • 日志文件:文本文件,记录实时发生的增删改的操作。可以用于恢复数据。加载速度慢,占空间
  • 快照,镜像:间隔存储。恢复速度快过日志文件,因为直接是二进制文件。弊端:容易丢失数据
    Hdfs同时用到了上述两种数据持久化,因为各有优点
    Editslog+FsImage
    在这里插入图片描述
    在这里插入图片描述

安全模式

安全模式是hadoop的一种保护机制,用于保证集群中的数据块的安全性。当集群启动的时候,会首先进入安全模式。当系统处于安全模式时会检查数据块的完整性。
假设我们设置的副本数(即参数dfs.replication)是3,那么在datanode上就应该有3个副本存在,假设只存在2个副本,那么比例就是2/3=0.666。hdfs默认的副本率0.999。我们的副本率0.666明显小于0.999,因此系统会自动的复制副本到其他dataNode,使得副本率不小于0.999。如果系统中有5个副本,超过我们设定的3个副本,那么系统也会删除多于的2个副本。
在安全模式状态下,文件系统只接受读数据请求,而不接受删除、修改等变更请求。在,当整个系统达到安全标准时,HDFS自动离开安全模式。30s
在这里插入图片描述
在持久化的时候,文件属性会持久化,但是文件的每个块不会持久化
在这里插入图片描述

SecondNameNode的交互与功能

在这里插入图片描述
secondarynamenode从namenode中通过http get获得edits,因为要和fsimage合并,所以也是通过http get 的方式把fsimage加载到内存,然后逐一执行具体对文件系统的操作,与fsimage合并,生成新的fsimage,然后把fsimage发送给namenode,通过http post的方式。在这里插入图片描述在这里插入图片描述
详细步骤:
第一步:将hdfs更新记录写入一个新的文件——edits.new。
第二步:将fsimage和editlog通过http协议发送至secondary namenode。
第三步:将fsimage与editlog合并,生成一个新的文件——fsimage.ckpt。这步之所以要在secondary namenode中进行,是因为比较耗时,如果在namenode中进行,或导致整个系统卡顿。
第四步:将生成的fsimage.ckpt通过http协议发送至namenode。
第五步:重命名fsimage.ckpt为fsimage,edits.new为edits。
第六步:fsimage与editlog合并的过程就完成了。
namenode和secondNameNode通信原理

namenode故障恢复

在我们的secondaryNamenode对namenode当中的fsimage和edits进行合并的时候,每次都会先将namenode的fsimage与edits文件拷贝一份过来,所以fsimage与edits文件在secondarNamendoe当中也会保存有一份,如果namenode的fsimage与edits文件损坏,那么我们可以将secondaryNamenode当中的fsimage与edits拷贝过去给namenode继续使用,只不过有可能会丢失一部分数据。这里涉及到几个配置选项

Block

抽象为block块的好处

  1. 一个文件有可能大于集群中任意一个磁盘
    10T*3/128 = xxx块 2T,2T,2T 文件方式存—–>多个block块,这些block块属于一个文件
  2. 使用块抽象而不是文件可以简化存储子系统
  3. 块非常适合用于数据备份进而提供数据容错能力和可用性

Block的放置策略

1版本是将第一和第二个副本放在同一机架,第三个副本在不同机架。但是如果只有两个副本的话,就会出问题。所以2.0版本变成了下面的样子。
在这里插入图片描述

块缓存

通常 DataNode 从磁盘中读取块,但对于访问频繁的文件,其对应的块可能被显示的缓存在 DataNode 的内存中,以堆外块缓存的形式存在。默认情况下,一个块仅缓存在一个DataNode的内存中,当然可以针对每个文件配置DataNode的数量。作业调度器通过在缓存块的DataNode上运行任务,可以利用块缓存的优势提高读操作的性能。

网络拓扑概念

在本地网络中,两个节点被称为“彼此近邻”是什么意思?在海量数据处理中,其主要限制因素是节点之间数据的传输速率——带宽很稀缺。这里的想法是将两个节点间的带宽作为距离的衡量标准。
节点距离:两个节点到达最近的共同祖先的距离总和。
例如,假设有数据中心d1机架r1中的节点n1。该节点可以表示为/d1/r1/n1。利用这种标记,这里给出四种距离描述:
Distance(/d1/r1/n1, /d1/r1/n1)=0(同一节点上的进程)
Distance(/d1/r1/n1, /d1/r1/n2)=2(同一机架上的不同节点)
Distance(/d1/r1/n1, /d1/r3/n2)=4(同一数据中心不同机架上的节点)
Distance(/d1/r1/n1, /d2/r4/n2)=6(不同数据中心的节点)
在这里插入图片描述

Hdfs读写流程

Hdfs写流程

客户端上传文件,NameNode会分配副本的放置位置
在这里插入图片描述

  1. Client 发起文件上传请求,通过 RPC 与 NameNode 建立通讯, NameNode 检查目标文件是否已存在,父目录是否存在,返回是否可以上传;
  2. Client 请求第一个 block 该传输到哪些 DataNode 服务器上;
  3. NameNode 根据配置文件中指定的备份数量及机架感知原理进行文件分配, 返回可用的 DataNode 的地址如:A, B, C;
  4. Client 请求 3 台 DataNode 中的一台 A 上传数据(本质上是一个 RPC 调用,建立 pipeline ),A 收到请求会继续调用 B,然后 B 调用 C,将整个 pipeline 建立完成, 后逐级返回 client;
  5. Client 开始往 A 上传第一个 block(先从磁盘读取数据放到一个本地内存缓存),以 packet 为单位(默认64K),A 收到一个 packet 就会传给 B,B 传给 C。A 每传一个 packet 会放入一个应答队列等待应答;
  6. 数据被分割成一个个 packet 数据包在 pipeline 上依次传输,在 pipeline 反方向上, 逐个发送 ack(命令正确应答),最终由 pipeline 中第一个 DataNode 节点 A 将 pipelineack 发送给 Client;
  7. 当一个 block 传输完成之后,Client 再次请求 NameNode 上传第二个 block,重复步骤 2。
    在这里插入图片描述

HDFS读流程

客户端读文件也是找距离最近,但也可以直接寻找到对应的块文件,而不是非要下载文件的所有块
在这里插入图片描述

  1. Client向NameNode发起RPC请求,来确定请求文件block所在的位置;
  2. NameNode会视情况返回文件的部分或者全部block列表,对于每个block,NameNode 都会返回含有该 block 副本的 DataNode 地址; 这些返回的 DN 地址,会按照集群拓扑结构得出 DataNode 与客户端的距离,然后进行排序,排序两个规则:网络拓扑结构中距离 Client 近的排靠前;心跳机制中超时汇报的 DN 状态为 STALE,这样的排靠后
  3. Client 选取排序靠前的 DataNode 来读取 block,如果客户端本身就是DataNode,那么将从本地直接获取数据(短路读取特性);
  4. 底层上本质是建立 Socket Stream(FSDataInputStream),重复的调用父类 DataInputStream 的 read 方法,直到这个块上的数据读取完毕;
  5. 当读完列表的 block 后,若文件读取还没有结束,客户端会继续向NameNode 获取下一批的 block 列表;
  6. 读取完一个 block 都会进行 checksum 验证,如果读取 DataNode 时出现错误,客户端会通知 NameNode,然后再从下一个拥有该 block 副本的DataNode 继续读
  7. read 方法是并行的读取 block 信息,不是一块一块的读取;NameNode 只是返回Client请求包含块的DataNode地址,并不是返回请求块的数据;
  8. 最终读取来所有的 block 会合并成一个完整的最终文件
    在这里插入图片描述
    在这里插入图片描述

Mapreduce

Mapreduce框架

Map

  • split是逻辑上的数据块,输入的是block,但考虑到不同算法的Io不同,所以可以划分为不同大小的split,(其实是为了IO效率着想)。默认情况下切片等于块。切片的多少可以控制并行度。所以map数量是由切片的数量决定的。
  • 切片会格式化出记录,以一条记录调用一次map方法。
  • 左边三个并行度是三个map过程。一个切片会对应一个map计算,之后会得到键值对,k,v的形式,但实际上(k,v)会参与分区计算,也就是使用k获得分区号p,最终得到的是(k,v,p)的形式。p表示分区。
  • map是一次记录调用一次方法,reduce是一组记录调用一次方法(group,就是key相同)
  • map task的输出是一个文件,存在本地系统中。
    在这里插入图片描述
  • map 的输出并不是一条记录一次,而是先存放在buffer缓冲区中,默认为100M,缓冲区满的时候就写入本地。
    在这里插入图片描述

key

  • 相同key值得分区一定相同,reduce会拉取相同分区的数据进行reduce操作
  • 右边的redube有两个框,所以并行度为2,reduce的并行度由人工决定。因为只有人自己才知道并行度的合适。框架默认的数量是1.
  • reduce计算需要计算相同的key值,一个reduce Task处理一个分区,包含一个或多个分组。组不能被分割,所以一组只能属于一个分区。
  • reduce处理数据使用的是迭代器模式,不会把数据全加载到内存,而是存放在磁盘。避免了处理大数据时的内存溢出。

shuffle(二次排序)

  • 因为map的数据存放在磁盘上。reduce需要把同一个分区的数据拉取出来,j就需要打开每个文件,再把分区找出来。在IO遍历中成本是很大的,所以最好是在存储的时候就已经把同一分区的数据放在一起。就是在每个buffer中进行分区排序,将一个分区中的数据排在一起。这些buffer的小文件就是内部有序,外部无序,所以就可以使用归并算法进行合并。
  • 除了分区排序,在同一个分区里面再进行key值排序。因为reduce是一次处理一组数据。如果一个分区里有1000组,那么需要打开文件1000次,Io成本太高。所以将相同的一组key排在一起。那直接打开文件一次,取出第一组进行计算,IO不关,再取第二组数据计算,IO成本下降。
  • reduce的归并排序其实可以和reduce方法的计算同时发生,尽量减少IO
    在这里插入图片描述
    在这里插入图片描述

MapReduce1.0运行模型

MapReduce工作流程最详细解释

在这里插入图片描述
在这里插入图片描述

  • JobClient.runJob() 还会做一件事,使用 InputFormat类去计算如何把 input 文件 分割成一份一份,然后交给 mapper 处理。inputformat.getSplit() 函数返回一个 InputSplit 的 List, 每一个 InputSplit 就是一个 mapper 需要处理的数据。
  • JobTracker 尽量把 mapper 安排在离它要处理的数据比较近的机器上,以便 mapper 从本机读取数据,节省网络传输时间。
  • 对于每个 map任务, 我们知道它的 split 包含的数据所在的主机位置,我们就把 mapper 安排在那个相应的主机上好了,至少是比较近的host. 你可能会问:split 里存储的 主机位置是 HDFS 存数据的主机,和 MapReduce 的主机 有什么相关呢?为了达到数据本地性,其实通常把MapReduce 和 HDFS 部署在同一组主机上。
  • Map通过 RecordReader 读取Input的key/value对,map根据用户自定义的任务,运行完毕后,产生另外一系列 key/value,并将其写入到Hadoop的内存缓冲取中,在内存缓冲区中的key/value对按key排序,此时会按照reduce partition进行,分到不同partition中,一旦内存满就会被写入到本地磁盘的文件里,这个文件叫spill file。

总结

原文链接:https://blog.youkuaiyun.com/qq_39657909/article/details/86500875

Map阶段

在这里插入图片描述
(1)Read阶段:MapTask通过用户编写的RecordReader,从输入InputSplit中解析出一个个key/value
(2)Map阶段:该节点主要是将解析出的key/value交给用户编写map()函数处理,并产生一系列新的key/value。
(3)Collect收集阶段:在用户编写map()函数中,当数据处理完成后,一般会调用OutputCollector.collect()输出结果。在该函数内部,它会将生成的key/value分区(调用Partitioner),并写入一个环形内存缓冲区中。
(4)Spill阶段:即“溢写”,当环形缓冲区满后,MapReduce会将数据写到本地磁盘上,生成一个临时文件。需要注意的是,将数据写入本地磁盘之前,先要对数据进行一次本地排序,并在必要时对数据进行合并、压缩等操作。
(5)Combine阶段:当所有数据处理完成后,MapTask对所有临时文件进行一次合并,以确保最终只会生成一个数据文件
(6)当所有数据处理完后,MapTask会将所有临时文件合并成一个大文件,并保存到文件output/file.out中,同时生成相应的索引文件output/file.out.index。
在进行文件合并过程中,MapTask以分区为单位进行合并。对于某个分区,它将采用多轮递归合并的方式。每轮合并io.sort.factor(默认10)个文件,并将产生的文件重新加入待合并列表中,对文件排序后,重复以上过程,直到最终得到一个大文件。
让每个MapTask最终只生成一个数据文件,可避免同时打开大量文件和同时读取大量小文件产生的随机读取带来的开销。
溢写:利用快速排序算法对缓存区内的数据进行排序,排序方式是,先按照分区编号Partition进行排序,然后按照key进行排序。这样,经过排序后,数据以分区为单位聚集在一起,且同一分区内所有数据按照key有序。
Combine阶段:归并排序

reduce阶段

在Reduce阶段,reduce()方法接受所有映射到这个Reduce的map输出后,也会调用job.setSortComparatorClass()方法设置的Key比较函数类,对所有数据进行排序。然后开始构造一个Key对应的Value迭代器。这时就要用到分组,使用 job.setGroupingComparatorClass()方法设置分组函数类。只要这个比较器比较的两个Key相同,它们就属于同一组,它们的Value放在一个Value迭代器,而这个迭代器的Key使用属于同一个组的所有Key的第一个Key。最后就是进入Reducer的
reduce()方法,reduce()方法的输入是所有的Key和它的Value迭代器,同样注意输入与输出的类型必须与自定义的Reducer中声明的一致
———————————————— 版权声明:本文为优快云博主「提灯寻梦在南国」的原创文章,遵循CC 4.0
BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.youkuaiyun.com/weixin_38073885/article/details/103938749

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值