1. 基本概念
1.1 hdfs是什么?
分布式的文件系统,由多个服务器联合起来实现功能。用来解决海量数据的存储问题。
1.2 hdfs概念和特性
hdfs有一个统一的命名空间——目录树
(1) hdfs文件系统会给客户端提供一个统一的抽象目录树,客户端访问hdfs文件时就是通过指定这个抽象目录中的路径来访问
(2) Hdfs中的文件都是分块(block)存储的,块的大小可以通过配置参数(dfs.blocksize)来规定,默认大小在hadoop2.x版本中是128M,老版本中是64M
(3) 文件的各个block由谁来进行真实的存储呢?----分布在各个datanode服务节点上,而且每一个block都可以存储多个副本(副本数量也可以通过参数设置dfs.replication)
(4) Hdfs中有一个重要的角色:namenode,负责维护整个hdfs文件系统的目录树,以及每一个路径(文件)所对应的block块信息(block的id,及所在的datanode服务器)
1.3 hdfs使用场景
hdfs是设计成适应一次写入,多次读出的场景,并不支持文件的修改(适合用来做数据分析)
hadoop不适合处理小文件,存储小文件的效率非常低,而且大量的小文件会造成namenode中的元数据过多,负载过高。
注:hdfs并不适合用来做网盘应用,因为,不便修改,延迟大,网络开销大,成本太高
2. Hadoop 各个节点的工作职责(Hadoop 2.6 HA 模式)
NameNode:(1)负责客户端请求的响应、(2)元数据的管理(查询,修改)、(3) 维护hdfs系统的目录树结构,记录每一个文件对应的block信息(block id, 服务器地址, 文件分成几块)
ResourceManager:负责整个集群的资源管理
ZKFC:负责切换主备的 namenode。
NodeManager:节点管理器是每个节点的代理框架。负责启动容器,监控容器的资源使用(cpu,内存,io),并把这些信息发送给调度器。
DataNode:存储管理用户的文件块数据
JournalNode:负责 active 和 standby namenode的元数据同步。
3. HDFS 合并元数据的过程
FSImage文件和EditsLog文件可以通过ID来互相关联。在参数dfs.namenode.name.dir设置的路径下,会保存FSImage文件和EditsLog文件,如果是QJM方式HA的话,EditsLog文件保存在参数dfs.journalnode.edits.dir设置的路径下。
在上图中可以看到,edit log文件以edits_开头,后面跟一个txid范围段,并且多个edit log之间首尾相连,正在使用的edit log名字为edits_inprogress_txid。该路径下还会保存两个fsimage文件,文件格式为fsimage_txid。上图中可以看出fsimage文件已经加载到了最新的一个edit log文件,仅仅只有inprogress状态的edit log未被加载。在启动HDFS时,只需要读入fsimage_0000000000000008927以及edits_inprogress_0000000000000008928就可以还原出当前hdfs的最新状况。
3.1 什么时候合并元数据
什么时候进行 checkpoint 由两个参数 dfs.namenode.checkpoint.preiod (默认值是3600,即 1 小时)和 dfs.namenode.checkpoint.txns (默认值是 1000000 )来决定。period 参数表示,经过 1 小时就进行一次 checkpoint,txns 参数表示,hdfs 经过 100 万次操作后就要进行 checkpoint 了。这两个参数任意一个得到满足,都会触发 checkpoint 过程。进行 checkpoint 的节点每隔 dfs.namenode.checkpoint.check.period (默认值是 60 )秒就会去统计一次 hdfs 的操作次数。
3.2 HA 模式下合并元数据的过程
在HA模式下checkpoint过程由StandBy NameNode来进行,以下简称为SBNN,Active NameNode简称为ANN。
主要由4个步骤:
SBNN 检查是否达到 checkpoint 条件:离上一次 checkpoint 操作是否已经有一个小时,或者 HDFS 已经进行了100万次操作。
SBNN 检查达到 checkpoint 条件后,将该 namespace 以 fsimage.ckpt_txid 格式保存到 SBNN 的磁盘上,并且随之生成一个 MD5 文件。然后将该 fsimage.ckpt_txid 文件重命名为fsimage_txid。
然后 SBNN 通过 HTTP 联系 ANN。
ANN 通过 HTTP 从 SBNN 获取最新的 fsimage_txid 文件并保存为 fsimage.ckpt_txid,然后也生成一个 MD5,将这个 MD5 与 SBNN 的 MD5 文件进行比较,确认 ANN 已经正确获取到了 SBNN 最新的 fsimage 文件。然后将 fsimage.ckpt_txid 文件重命名为 fsimage_txit。
通过上面一系列的操作,SBNN 上最新的 FSImage 文件就成功同步到了 ANN 上。
4. HDFS 读写数据的流程
4.1 读数据流程
client跟namenode通信查询元数据,找到文件块所在的datanode服务器
分别连接目标datanode,并发读取文件块,并在合并读取到的文件
4.2 写数据流程
1.根namenode通信请求上传文件,namenode检查目标文件是否已存在(文件已存在则报错不能上传),父目录是否存在(目录不存在报错无法上传),以及客户端是否有新建文件的权限。
2.namenode返回是否可以上传,如果可以上传,namenode会返回这个文件是否被分块以及分块的具体信息。
3.client请求第一个 block该传输到哪些datanode服务器上
4.namenode返回3个datanode服务器ABC
5.client请求3台dn中的一台A上传数据(本质上是一个RPC调用,建立pipeline,连接离自己最近的datanode),当第一个datanode写完后,这个datanode会将剩余的两个副本进行水平备份
6.内部会维护一个确认队列"ack queue",收到所有datanode确认信息后,才确认数据块写入完毕了。
7.当一个block传输完成之后,client再次请求namenode上传第二个block的服务器,以此类推。
- 如果传输过程中,有某个 datanode 出现了故障,那么当前的 pipeline 会被关闭,出现故障的 datanode 会从当前的 pipeline 中移除,剩余的 block 会继续剩下的 datanode 中继续以 pipeline 的形式传输,同时 Namenode 会分配一个新的 datanode,保持 replicas 设定的数量。
5. NameNode 如何实现高可用
在主备切换上Zookeeper可以干的事:
失败探测 在每个NameNode启动时,会在Zookeeper上注册一个持久化的节点,当这个NameNode宕机时,它的会话就会终止,Zookeeper发现之后,就会通知备用的NameNode,Hi,老兄,你该上岗了。
-
选举机制, Zookeeper提供了一个简单的独占锁,获取Master的功能,如果那个NameNode发现自己得到这个锁,那就预示着,这个NameNode将被激活为Active状态
当然,实际工作中Hadoop提供了ZKFailoverController角色,在每个NameNode的节点上,简称zkfc,它的主要职责如下:
健康监测,zkfc会周期性的向它监控的NameNode发送健康探测命令,从而来确定某个NameNode是否处于健康状态,如果机器宕机,心跳失败,那么zkfc就会标记它处于一个不健康的状态
会话管理,如果NameNode是健康的,zkfc就会在zookeeper中保持一个打开的会话,如果NameNode同时还是Active状态的,那么zkfc还会在Zookeeper中占有一个类型为短暂类型的znode,当这个NameNode挂掉时,
这个znode将会被删除,然后备用的NameNode,将会得到这把锁,升级为主NameNode,同时标记状态为Active,当宕机的NameNode,重新启动时,它会再次注册zookeper,发现已经有znode锁了,便会自动变为Standby状态,如此往复循环,保证高可靠,需要注意,目前仅仅支持最多配置2个NameNode。master选举,如上所述,通过在zookeeper中维持一个短暂类型的znode,来实现抢占式的锁机制,从而判断那个NameNode为Active状态。
6. HDFS 的副本如何存放
第一个block副本放在和client所在的node里(如果client不在集群范围内,则这第一个node是随机选取的)
第二个副本放置在与第一个节点不同的机架中的node中(随机选择)。
第三个副本放置在与第一个副本所在节点同一机架的另一个节点上。
如果还更多的副本就随机放在集群的node里。