业内跳转链接:
分布式存储系统HDFS
- 主要解决大数据的数据存储问题。
- 分布式 : 分布式系统是由一系列的计算机组成的 , 收集、整理、处理海量的数据,但用户使用时感知不到背后的逻辑,就像访问单台计算机一样
- 扩展知识:
-
Hadoop的定义
- 狭义:hadoop1=hdfs1+MR1
Hadoop2=hdfs2+MR2+Yarn - 广义: Hadoop生态系统
- 狭义:hadoop1=hdfs1+MR1
-
Hadoop的思想之源:
- Google 03年发布3大论文, GFS、mapreduce、 Bigtable . 可谓是旧时代的三驾马车
-
HDFS的优缺点
- 优点:
- 1.分布式角度
- 处理海量数据 , 入门级就是PB
- 百万规模以上的文件数量: 10k+/节点
- 适合进行批处理(一个一个执行的命令汇总起来,成批的执行)
- 2.自身角度
- 可以在廉价的机器上构建
- 高可靠性:多副本策略,数据不易丢失
- 高容错性:数据自动保存副本;如果副本丢失,还有自动恢复机制.
- 1.分布式角度
- 缺点:
- 低延迟高数据吞吐访问问题
- 不支持毫秒级
- 吞吐量大但限制于延迟(磁盘io和网络io瓶颈)
- 小文件存取占用NameNode大量内存 , 会产生一个去寻找文件的时间比传输文件的时间花的更多的问题
- 不支持文件修改:只支持append追加 , 但是不是不可以,只是为了性能和成本 ,空间来换时间 .
- 低延迟高数据吞吐访问问题
hadoop1.x版本 HDFS的功能模块及原理
- HDFS数据存储模型 : block
-
关系型数据库的最小存储单元是一行,HDFS文件存储的过程是一个文件被线性切割成固定大小的数据块:block
1️⃣ (hadoop1.x):block数据块的最大单位默认是64M,
2️⃣ (hadoop2.x):最大单位扩大到了默认128M
3️⃣ block的最大单位是支持自定义的.
4️⃣ 最小单位是1个字节.引申的问题: haoop1.x默认64M , 2.x默认128M , 3.x默认256M , 为什么要这么划分 ?
我们先来谈一下为什么不能少于64MB,128MB,256MB? 答案引自网络:https://chenghuiz.iteye.com/blog/2381884首先 , 减少硬盘寻道时间 , 普通文件系统的一个数据块大小一般是4KB , 为了保证能支持大容量的流式数据操作,所以hdfs的数据读写操作,涉及到的数据量都是比较大的。 你一个block块设置太小, 要操作的数据大小不变的情况下 , 你就需要比原来多读或者多写 , 一个数据储存的时候被线性分隔成多个block块 , 这些block在硬盘的储存是非连续存储的,普通硬盘因为需要移动磁头,所以随机寻址是比较慢的,读写操作的block块数量越多 , 硬盘寻道的时间就会越多 。当硬盘寻道时间比读写数据的时间还要长的时候,就造成了低延迟高数据吞吐访问问题了 , 硬盘寻道时间是系统的一个瓶颈。合适的block块大小有助于减少硬盘寻道时间,提高系统吞吐量 。
其次 , 减少Namenode内存消耗 , 对于HDFS系统来说 ,他仅有一台NameNode服务器, 哪怕是hadoop2.x也只是多了一台高可用的备份机 , 相较于可以有多台的DateNode , NameNode的内存是极其有限切珍贵的 . NameNode的功能之一就是在内存中FSImage文件中记录DateNode的block块的位置信息 , 如果你block块的单位小了 , block块的数量多了 , FSImage文件要记录的DateNode的block块信息是不是也变多了? 伤不起 , 还是那句话 , NameNode的内存资源是宝贵的 .那么综上所述 , block块的大小是不是越大越好呢? 当然也不是的
在MapRduce框架中 , 如果在Map阶段奔溃 , 系统就需要重新启动,重新启动就需要重新加载数据,如果你block块越大,数据加载时间越长,系统恢复过程越长 . 监管时间问题:主节点监管其他节点的情况,每个节点会周期性的把完成的工作和状态的更新报告回来。如果一个节点保持沉默超过一个预设的时间间隔,主节点记录下这个节点状态为死亡,并把分配给这个节点的数据发到别的节点。对于这个“预设的时间间隔”,这是从数据块的角度大概估算的。假如是对于64MB的数据块,我可以假设你10分钟之内无论如何也能解决了吧,超过10分钟也没反应,那就是挂了。可对于1G以上的数据,我应该要估算个多长的时间内?估算的时间如果太短了,那就误判死亡了,分分钟更坏的情况是所有节点都会被判死亡。估算的时间太长了,那等待的时间就过长了。所以对于过大的数据块,这个“预设的时间间隔”不好估算。问题分解问题:
数据量大小是问题解决的复杂度是成线性关系的。对于同个算法,处理的数据量越大,它的时间复杂度也就越大约束Map输出: 在Map Reduce框架里,Map之后的数据是要经过排序才执行Reduce操作的。想想归并排序算法的思想,对小文件进行排序,然后将小文件归并成大文件的思想,然后就会懂这点了…
-
- 数据文件的存储策略
- 数据文件根据block块的默认大小切分成若干个block ,存储到不同节点上,如果相同block块在同一台DateNode节点不会被储存多分 , 会覆盖
- 默认情况下每个block块都会产生2个副本 , 加上它自身一共3个副本,安全可靠
- 副本数量可以自定义不要大于节点数 , 副本数大于节点数的blog块就会覆盖blog块 , 既不产生效果 , 又浪费性能
- Block大小和储存副本的数量, 在Client端上传文件时进行设置,文件上传成功后副本的数量可以变更,Block块的大小不可变更
- 数据文件根据block块的默认大小切分成若干个block ,存储到不同节点上,如果相同block块在同一台DateNode节点不会被储存多分 , 会覆盖
解读:
- 上图这种情况下一个文件被线性切分的每个block块都有三个副本 , 最多有2台服务器宕机情况下,文件也是安全的 , 如果这时候还有其他服务器 , 系统会挑选2台服务器 , 进行2份备份(自动恢复机制)
hdoop1.x架构
- 1 . NameNode
- NameNode的主要功能:
- 接受客户端读写操作的请求
- 接受各DateNode服务器节点 , 心跳保持汇报的服务器节点信息(block块位置信息 , 磁盘 , CPU …)
- NameNode会将metadate元数据信息储存到磁盘中的"FSImage"的镜像文件中.
- 每次NameNode一启动,从FSImage镜像文件将metadate元数据信息加载到NameNode服务器内存中.
- 对metadate元数据信息进行的操作会被专门记录到一个操作日志文件:edits日志文件中
- metadate元数据信息和edits操作日志会在特定条件下被SecondaryNameNode服务器进行合并,所谓特定条件就是: 3600秒合并一次或者edits操作日志的大小超过默认的最大值64M时进行合并
- 读写操作:
-
1 . 客户端写文件时,NameNode根据DataNode每3秒汇报的节点信息 , 随机挑选一台磁盘不太满,CPU不太忙的节点让客户端将文件写入. 之后将第二个副本放置于和第一个副本不同的机架的节点让客户端将文件放置. 第三个副本指定于与第二个副本相同机架的不同节点让客户端将文件放入.
-
2 . 客户端在读取文件时,NameNode根据DateNode心跳保持每3秒汇报的block块位置信息,根据ip地址从近到远的顺序挑选读取block块的服务器节点 , 结合metadate元数据信息的偏移量(offset) , 指定客户端去哪台服务器节点读取数据\
-
- NameNode的主要功能:
- 2 . SecondaryNameNode
- SecondaryNameNode主要工作是帮助NameNode合并edits log文件和metadate元数据信息,这样可以减少NameNode的启动时间,它并不是NameNode的备份机 , 你可以称呼它为秘书机 (但是它也可以做备份)。
- SecondaryNameNode执行合并时间和机制
•A、根据配置文件设置的时间间隔fs.checkpoint.period
默认3600豪秒
•B、根据配置文件设置edits log大小fs.checkpoint.size
规定edits文件的最大值默认是64MB - SecondateNameNode服务器合并metadate元数据信息和Edits操作日志合并成新的metadate元数据后,edits操作日志会清空.
- 3 . DateNode
- 存储数据(Block)
- 启动DateName线程的时候会向NameNode汇报block位置信息
- 通过向NameNode发送心跳保持与其联系(3秒一次),如果NameNode 10分钟没有收到DateNode的心跳,则认为其已经挂了,并重新拷贝一份副本到其它DateNode节点.
- Block的副本放置策略
- 第一个副本:放置在上传文件的DN;如果是集群外提交,则随机挑选一台磁盘不太满,CPU不太忙的节点。
- 第二个副本:放置在于第一个副本不同的机架的节点上。
- 第三个副本:与第二个副本相同机架的不同节点。
- 更多副本:随机节点
(副本存放策略图)
HDFS读写流程
- 读文件过程
- 1.首先调用FileSystem对象的open方法,其实是一个DistributedFileSystem的实例。
- 2.DistributedFileSystem通过rpc协议获得文件的第一批block的locations地址,(同一个block按照重复数会返回多个locations,因为同一文件的block分布式存储在不同节点上),这些locations按照hadoop拓扑结构排序,距离客户端近的排在前面(就近原则选择)。
- 3.前两步会返回一个FSDataInputStream对象,该对象会被封装DFSInputStream对象,DFSInputStream可以方便的管理datanode和namenode数据流。客户端调用read方法,DFSInputStream最会找出离客户端最近的datanode并连接。
- 4.数据从datanode源源不断的流向客户端。
这些操作对客户端来说是透明的,客户端的角度看来只是读一个持续不断的流。- 5.如果第一批block都读完了, DFSInputStream就会去namenode拿下一批block的locations,然后继续读,如果所有的块都读完,这时就会关闭掉所有的流。
如果在读数据的时候,DFSInputStream和datanode的通讯发生异常,就会尝试正在读的block的排序第二近的datanode,并且会记录哪个datanode发生错误,剩余的blocks读的时候就会直接跳过该datanode。 DFSInputStream也会检查block数据校验和,如果发现一个坏的block,就会先报告到namenode节点,然后DFSInputStream在其他的datanode上读该block的镜像。- 6 该设计就是客户端直接连接datanode来检索数据并且namenode来负责为每一个block提供最优的datanode, namenode仅仅处理block location的请求,这些信息都加载在namenode的内存中,hdfs通过datanode集群可以承受大量客户端的并发访问。
- 写文件流程
- 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都表示已经收到数据的时候,这时ack quene才会把对应的packet包移除掉。 如果在写的过程中某个datanode发生错误,会采取以下几步:
1) pipeline被关闭掉;
2)为了防止丢包。ack quene里的packet会同步到data quene里;创建新的pipeline管道怼到其他正常DN上
3)剩下的部分被写到剩下的两个正常的datanode中;
4)namenode找到另外的datanode去创建这个块的副本。当然,这些操作对客户端来说是无感知的。- 6.客户端完成写数据后调用close方法关闭写入流。
站在hadoop2.x的角度批斗hadoop1.x
- HDFS
- NameNode压力过大,内存受限,系统扩展性差
- NameNode单点故障,NameNode宕机系统就瘫痪了,在线场景中难以应用.
- MapReduce
- JobTracker访问压力大,影响系统扩展性
难以支持除MapReduce之外的计算框架,比如Spark、Storm等.
hadoop 2.x
- HDFS:分布式文件存储系统;
- YARN:资源管理系统
(HDFS架构)
- Hadoop 2.0新引入的资源管理系统,直接从MRv1演化而来的;
- 将MRv1中JobTracker的资源管理和任务调度两个功能分开,分别由ResourceManager和ApplicationMaster进程实现。
- ResourceManager: 负责整个集群的资源管理和调度。
- ApplicationMaster:负责应用程序相关的事务,比如任务调度、任务监控和容错等。
- YARN的引入,使得多个计算框架可运行在一个集群中
- 每个应用程序都会对应一个ApplicationMaster
- 目前多个计算框架可以运行在YARN上,比如MapReduce、Spark、Storm
等。
- MapReduce:运行在YARN上的MR;
- hadoop2.x结构图
- 解析
- DateNode心跳保持,每3秒向NameNode发送相关信息.
- 2.x的架构支持2个NameNode节点
- NameNode接受读写服务,将元数据信息交给JournalNode(JN).
- 2台NameNode,谁拿到竞争锁,谁就是active,另外一台作为备份standby,active的NameNode宕机之后会释放竞争锁,另一台NameNode就会持有竞争锁,进入active状态
- journalNode是一个集群,至少3台及以上,对NameNode提交的对元数据信息进行读写保存操作.journalNode的副本备份策略是过半原则:3台服务器最少备份2份,集群基本是奇数量的服务器.
- Zookeeper服务器的作用是帮助NameNode之间做主备切换
- FailoverControllerActive:竞争锁,NameNode服务器谁抢到谁就是主,余者备
- 解决单点故障
-部署了2台NameNode,服务器启动时,抢到竞争锁的NameNode对外提供服务(active),另一台NameNode(Standby),同步NameNode(active)的元数据,通过JN服务器,所有DataNode需要同时向两台NameNode汇报信息.
- 主备NameNode之间的切换:1.手动切换,通过命令实现,常用于HDFS升级的场合. 2.自动切换:基于Zookeeper实现
- YARN资源管理任务调度流程
- - 客户端提交一个任务或者请求或者操作给yarn的ResourceManager资源管理,ResourceManager掌握整个集群的资源
- ResourceManager会根据它掌握的信息,随机找一台DateNode启动ApplicationMater进行任务调度.
- ApplicationMaster启动后,开始任务调度,向ResourceManager请求资源,用来启动进程(Executor),执行任务
- ResourceManager将任务的资源信息返回给ApplicationMaster
- ApplicationMaster获得资源信息 , 去执行任务.去指定的DateNode启动进程,然后对应的资源返回给客户端
HDFS命令
- 启动HDFS集群
start-dfs.sh
(在各服务器启动,防火墙关闭的情况下)
- 关闭HDFS集群
stop-dfs.sh
- 上传test文件到hdfs
hdfs dfs -put [上传文件的路径] [hdfs上存放的路径]
|hdfs dfs -put /home/a.txt /hdfs/test
- 查看HDFS命令文档
hdfs dfs
- 显示文件(夹)大小.
hdfs dfs -du [-s][-h]URI[URI ...]
- 在hdfs创建文件[夹]
hdfs dfs -mkdir [创建文件路径]
- 在hdfs删除
hdfs dfs -rm -r [删除文件路径]
- 复制文件(夹),可以覆盖,可以保留原有权限信息
hdfs dfs -cp [-f][-p|-p[topax]] [要拷贝的文件路径] [拷贝到的文件路径]
- 列出文件夹数量、文件数量、内容大小.
hdfs dfs -count [-q][-h]<paths>
- 修改所有者.
hdfs dfs -chown [-R][OWNER][:[GROUP]]URI[URI]
- 修改权限.
hdfs dfs -chmod [-R]<MODE[,MODE]...|OCTALMODE>URI[URI ...]