一、HDFS介绍
HDFS是分布式文件系统。windows文件系统常见有fat32、ntfs,linux下 常见是ext3、ext4,还有很多其他文件系统。不同类别的文件系统存储数据的格式不一样。
二、HDFS1.0基础
1.HDFS1.0系统架构
- 主(叫Master)和多个从(Slave或Worker)分别部署到不同机器上。主机器除了NameNode还有SecondaryNameNode(它并不是一个NameNode,仅仅是镜像文件,是数据的备份)。NameNode和DataNode其实是两个完全不同进程(注意是进程)。
- HDFS1.0由3个组件构成 : NameNode(目前只能启动一个) 、 SecondaryNameNode 、 DataNode(每一台机器只能启动一个,但是多台机器会有多个)。
2.角色
- HDFS角色一共三个:主、从、client(client是提交任务的客户端)。
- Client的读操作:从DataNode上读,由NameNode告诉目标位置DataNode。
- DataNode存储数据最小单元block(如下图的绿色小方块,默认64M,可以修改,block大小直接影响map并发个数)
- NameNode存储元数据。
3.组件
NameNode、SecondaryNameNode 、 DataNode
I. NameNode
(1)NameNode:如下图
NameNode主要两个映射:文件名(客户端开发操作针对文件) -> block、block -> datanode(对应机器,一个机器只有一个datanode)。datanode的映射有block -> path。
(2)Namenode的隐患:
- Namenode进程挂了就不提供服务。
- HDFS1.0集群规模扩大问题:Namenode元数据存储在内存中,当集群规模特别大挂载了很多DataNode节点,DataNode节点有很多文件,文件背后有很多block,会发现这个数据非常庞大,那完全存在于内存中是吃不消的。一旦数据变大后,一方面是不能及时持久化,另外方面是不能永远膨胀下去,所以它直接制约着集群规模的扩大。HDFS1.0不提供集群规模扩大的解决。
- HDFS倾向存储大文件。如果文件越小,存储同等大小文件所需要的元信息就越多,导致了NameNode存储压力更大。:HDFS存储一个文件和100个文件是不一样的,假如一个文件只有几K,它仍然按照如64M为单位的容器去存储,每一个文件独占至少一个block,这样大大降低了集群使用效率。如下图:
(3)元信息持久化
- 元信息主要存储在内存中且不断变化,也会存储在磁盘中,磁盘信息怎么得到和SecondaryNameNode 有关。
- 元数据存储在两个地方:一个是内存中,对外提供服务;另一个是本地磁盘中,不对外提供服务,可认为是数据备份,这个数据备份名字是fsimage,在系统运行期间会对NameNode内存的元数据定期保存到文件fsimage(某时刻镜像)。比如今天跑集群跑了几小时,每个小时的数据可能会持久化到每一个edits文件中,它只dump修改的部分。fsimage可能是一、两天等之前的数据,edits是实时更新的。所以并且edits文件和fsimage文件会被SecondaryNameNode进程周期性的合并。
(4)单个NameNode问题解决方案:
如下图:第一种解决方案有延迟;第二种通过编辑日志文件edits合并命名空间镜像fsimage,它的目的是恢复时尽可能保留更多信息,难免也会导致丢失部分数据。
II. DataNode
- 所有的数据块存储在DataNode。
- 听从NameNode指示。
- 心跳机制:定期报告DataNode存储的规模、健康状态。一个是假如DataNode马上要挂了,网络传输心跳不能保证每3s一次,心跳不稳定有些抖,这时NameNode根据心跳不稳定判断这个DataNode失效,然后从集群中把这个DataNode节点移除掉。另外一个是假如DataNode存储的数据空间已经达到一定状态时,NameNode不会划分更多的数据去存储。
- 与DataNode交互(副本拷贝):某机器挂了需要DataNode之间的副本拷贝、写数据也会涉及副本拷贝。
如下图:
III.SecondNameNode
(1)SecondNameNode基础,如下图:
- 重启时内存是空的,由于这些信息是在内存的,SecondNameNode是为了考虑持久化到磁盘。
- NameNode重启时,edit logs会自动与fsimage合并merge,得到最新快照。
(2)SecondNameNode
- 由于NameNode很少重启,意味着任务运行很长时间后edit logs文件个数会很多并且总体来说文件量也很大。面临两个问题:edit logs文件变大如何管理文件、当edits变大时加载edit logs时间变长并且做合并耗时更长导致重启时间长。为了避免edit logs很大这种情况,SecondNameNode提供一个机制尽可能减小edit logs,并且保持fsimage最新。
- SecondNameNode定时到NameNode去获取edit logs,并更新到自己的fsimage。总共有两个fsimage:真正加载的是NameNode的fsimage(如下图右下角);还有一个用于备份的fsimage(如下图左下角),由SecondNameNode来写,其永远比NameNode的fsimage要新。
- 一旦它有了新的fsimage文件,它将其拷贝回NameNode中。
- NameNode在下次重启时会使用这个新的fsimage文件,从而减少重启的时间。
4.机架感知策略-block副本放置策略
- 机架感知策略直接和副本数有直接关系,集群默认3副本,这3副本存在同一机器上当然不支持,放在同一机柜上也有风险如机柜裂了。需要考虑一种策略尽量把风险分散开。
如下图:
- 一个机柜Rack1放一个副本,另外一个机柜Rack2放第二个副本,再在这个机柜的另外随机一台机器放第三个副本。IDC表示机房,distance(/D1/R1/H1,/D1/R1/H3)=2表示distance(第一个副本,另外一个副本)表示distance(机房1/机架1/机器1,机房1/机架1/机器3)。
5.数据完整性校验
- crc32循环冗余校验码,类似于签名,也叫校验和(crc32返回的结果)。
- 两种校验方法:
- 校验和:默认每512字节创建一个校验码,这里假如每 “===” 占用的字节创建校验码,用全部数据创建校验码显然不合适。数据是从头往后传输的,client -> datanode -> block(client写数据的校验工作),client往datanode传输要写的数据,datanode接受一部分数据就做一次校验码,此新生成的校验码和client传过来的校验码对比,如果一样的话就认为数据是准确无误的,按部就班写入block中,如果不一样认为数据损坏把数据丢弃。
校验码1 | 校验码2 | 校验码3 …
=== | === | === | === | === | = - 数据块检测程序DataBlockScanner:在DN(DataNode)节点上开启一个后台线程DataBlockScanner,为了保证数据可用性定期检查整个DN(DataNode)上的数据块有没有变动,因为数据随着时间推移有可能数据变化,一旦检测数据块有问题,在心跳阶段DN会收到NN(NameNode)发送的一个block修复命令(从其他数据块进行拷贝一个新的数据块 ,损坏的数据块丢掉,重新达到副本平衡)。如dn(datanode ) -> client(client读数据的校验工作),client仅仅使用datanode传过来的上一次校验码(时间为datanode日志记录的最新时间产生的校验码,不是特别实时)和对传输的数据做的编码对比,如果验证通过则更新日志和记录的时间。
- 校验和:默认每512字节创建一个校验码,这里假如每 “===” 占用的字节创建校验码,用全部数据创建校验码显然不合适。数据是从头往后传输的,client -> datanode -> block(client写数据的校验工作),client往datanode传输要写的数据,datanode接受一部分数据就做一次校验码,此新生成的校验码和client传过来的校验码对比,如果一样的话就认为数据是准确无误的,按部就班写入block中,如果不一样认为数据损坏把数据丢弃。
- 三次校验:client读(如上述数据块检测程序DataBlockScanner举例)、client写(上述校验和的举例)、DataBlockScanner线程。
6.可靠性
- 一个名字节点和多个数据节点:namenode单点有问题。
- 数据复制(冗余机制)
- 三副本保障
- 存放的位置(机架感知策略)
- 故障检测
- 数据节点
- 心跳包(检测是否宕机)
- 块block报告report(安全模式下检测)
- 数据完整性检测(校验和比较)
- 名字节点(日志文件,镜像文件):如fsimage和edit logs
- 数据节点
- 空间回收机制
- Trash目录:为了支持hdfs这一功能,需要配置core-site.xml文件。
7.H D F S 特 点
- 能做什么
- 存储并管理PB级数据
- 处理非结构化数据:非结构化数据有邮件、聊天记录、评论、照片、视频、pdf一些文档等。非结构化数据变成结构化数据方式:特别是hive,还有hbase等。
- 注重数据处理的吞吐量:操作系统有buffer预写的优化,读了上一条记录,提前把下一条记录提前读了出来,提高了数据读取的速度,如果数据不大就不能很好凸显出来。HDFS有这样优势大大提高了吞吐量。
- 应用模式:write-once-read-many存取模式。HDFS数据写了一般不能修改,但是要修改的话(不建议),像本地读文件是通过从文件头指针偏移定位到这个文件的某一个位置,修改可以通过这样的方式进行数据的插入。严格来说hdfs可以这样做但是不建议,因为非常影响效率。建议数据错了的话删了重新来一遍,还有数据想更新可以追加append,因为追加的方式会提高数据的吞吐效率。
- 不适合做:不建议做不代表不能做。大量随机读不建议是因为通过文件指针效率不高。需要对文件修改(不支持),要是修改只能append。 多用户写入(不支持):write-once-read-many是指一个人写多个人读,一般hdfs数据写好后更多是对外去读。
8.H D F S 写 流 程
首先判断是否有写的权限且该路径是否文件已存在。
4&5步骤解释:FSDataOutputStream类会把原始数据分成小的数据块,然后把这些数据块写到一个队列中,Data Streamer会读取这个队列,通过一个分发机制(把一个文件形成多个副本存在dn(datanode)中。它不是三个副本全部写完成功才返回ack,而是一旦有一个副本写完就会返回ack(有一个节点写成功即记录为成功),如果环境中没有达到3副本情况就谁有数据谁对外提供服务,然后内部做replication复制达到3副本(弱一致性)。
9.H D F S 读 流 程
nn告诉client数据块位置,FSDataInputStream类直接定位到机器位置去读。
10.H D F S & M a p R e d u c e 本 地 模 式
如下图:虚线框表示一个机器,发现nn(NameNode)和JobTracker部署在一起,dn(DataNode)和TaskTracker部署在一起。nn和dn是HDFS的进程,JobTracker和TaskTracker是MapReduce的进程。
nn和JobTracker一定要部署在一起吗?
小集群的时候可以部署在一起,如果是真正大型集群或工业型集群这两个要分开部署,分开到不同机器上。