HDFS 基础知识(上)
大家好,好久不见,我是大圣,明天更新一篇 HDFS 基础知识的文章。话不多说,间接上纲要
简略说一下最近的安顿,我会出一个 HDFS 系列的文章,让大家从理解 HDFS 根底开始,始终到相熟 HDFS 外围源码。文章的次要系列包含以下几个局部:
1 .HDFS 基础知识
2 . HDFS 源码图解
那接下来,咱们开始明天的内容。
1.HDFS 架构演变
1.1 hadoop 简介
Hadoop 到目前为止倒退曾经有 10 余年,版本经验了无数次的更新迭代,目前业内大家把 Hadoop 大的版本分为 Hadoop1,Hadoop2,Hadoop3 三个版本。
hadoop1 版本刚进去的时候是为了解决两个问题:一个是海量数据如何存储的问题,一个是海量数据如何计算的问题。Hadoop1 的外围设计就是 HDFS 和 MapReduce。HDFS 解决了海量数据如何存储的问题 ,MapReduce 解决了海量数据如何计算的问题。
HDFS 的全称:Hadoop Distributed File System
1.2 HDFS 的重要性
大数据中最重要的两个货色就是存储和计算,在存储方面当初大部分的公司都采纳 HDFS 作为底层的数据存储。如果公司大数据存储经常出现问题,那么就可能导致数据不可用,或者数据失落,这在生产环境是齐全不容许的。
比方还有数据小文件问题,数据文件过大导致查问速度过慢等问题,如果这些问题常常存在,那么会导致咱们的数据平台是不可用的。所以我认为公司的大数据存储是大数据中比拟根底而且最重要的一环。
所以对 HDFS 还是很值得深入研究的,一方面它作为大数据的底层存储的重要性显而易见,另一方面对 HDFS 理解比拟深刻,它待遇是真的好呀,如下图:
1.3 HDFS 的架构演进之路
HDFS 是 Hadoop 外面的一个组件,下面说过 Hadoop 通过了 hadoop1,Hadoop2,Hadoop3 三个大的版本迭代,所以 HDFS 也经验了 HDFS1,HDFS2,HDFS3 三个版本的迭代。
1.4 分布式文件系统
我集体的了解,其实分布式文件系统就是一个超级大型的电脑,因为分布式文件系统对于用户是无感知的,用户是不晓得你这个文件系统是分布式的,他用起来就和一台电脑外面存储是一样的,只是咱们在底层利用多台服务器对数据进行分片和冗余来进行存储,来达到对这个零碎的程度扩大。其实不光分布式存储,分布式计算也是的。
1.5 HDFS1
1) HDFS1 架构
HDFS1 是一个主从式的架构,主节点只有一个叫 NameNode。从节点有多个叫 DataNode。
NameNode 次要治理元数据(文件目录树):
- 文件与 Block 块,Block 块 与 DataNode 主机的关系。
- NameNode 为了疾速响应用户的操作申请,所以把元数据加载到了内存外面
DataNode 次要工作:
- 存储数据,把上传的数据划分成为固定大小的文件块(Hadoop1,默认是 64M)
- 为了保障数据安全,每个文件块默认都有三个正本
当初咱们有一个 给你一朵小红花.mp4 的文件,总共 128M,如果咱们要进行存储的话,首先客户端向 NameNode 发送要存储这个文件的申请,而后把这个文件宰割成两个 block 块,接着在 NameNode 外面会记录这个文件被分成了几个 block 块,而后决定这几个 block 存储到哪些 DataNode 服务器下面。
这里为了数据的安全性,所以咱们进行了数据冗余,就是把一个 block 块减少了 两个正本,其实分布式存储就是分区和冗余,咱们这里叫分块和冗余。
2)HDFS1 的毛病
HDFS1 有两个毛病:
1)NameNode 单点故障的问题
NameNode 这个主节点过程只有一个,如果这个过程宕机挂了,会导致 HDFS 不可用。
2)NameNode 内存受限的问题
当咱们的元数据原来越多的时候,咱们的 NameNode 单台服务器的内存会不够用。这个时候有人说,咱们能够给 NameNode 加内存,然而你再加内存,元数据还是会越来越多。再说单台机器的内存再去减少是有下限的,所以这个计划不可取。
1.6 HDFS2
HDFS2 次要解决了 HDFS1 中的两个问题,上面咱们来具体说一下 HDFS2 怎么解决 HDFS1 中的这个两个问题的。
1)单点故障解决方案
在 HDFS1 中 主节点 NameNode 只有一个,所以存在单点故障(SPOF)问题。
计划 1:
既然 NameNode 只有一个,那么咱们能够再弄一个 NameNode 就能够了,而后再客户端往第一个 NameNode 写过数据之后,这个 NameNode 再把元数据同步给另外一个 NameNode,这样不就能够了吗?如下图:
我认为这样是不行的,因为架构设计的时候要求低耦合,如果咱们这样设计的话,两个 NameNode 的耦合度太高了,扩展性会十分不好。
计划 2:
既然咱们应用 NameNode 往另外一个 NameNode 同步元数据这样耦合度太高的话,咱们能够利用第三方框架去升高这个耦合度。
然而咱们要留神,在咱们应用第三方框架去升高两个 NameNode 的耦合度的时候,咱们要确保引入的这个第三方框架它本人自身是没有单点故障这个问题的,要不然咱们的本意是为了解决 NameNode 的单点故障问题,你引入了第三方框架,而这个第三方框架自身也有单点故障的问题,这样是不合理的。
咱们这外面采纳的是 JournalNode 集群来升高这两个 NameNode 之间的耦合度,如下图:
这个 JournalNode 有几个特点:
1)个别是奇数台,且只有失常对外提供服务的机器大于 n /2,整个集群就能够失常对外提供服务
2)这个集群具备强事务性,就是我去那一台 JournalNode 服务器去读取数据的时候,读取的都是最新的数据
有了这个 JournalNode 集群,就能够升高两个 NameNode 之间的耦合性,右边这个 NameNode 的数据能够写入到 JournalNode 集群外面,而后左边这个 NameNode 能够间接从 JournalNode 集群外面读取数据就能够了。其实你能够把这个 JournalNode 集群了解为 Kafka 集群,就是用来解耦的。
到这里看起来仿佛能够解决了单点故障问题,那咱们接下来看一个这样的场景。当在凌晨三点的时候,某公司运维工程师 张三正在做美梦,忽然接管到咱们下面架构外面的 NameNode 忽然宕机了,而后他就要赶快起来,收到把状态为 StandBy 的 NameNode 给切换成 Active。
如果这样来回搞几次,张三会解体的,所以下面的框架还缺一个当 状态为 Active 的 NameNode 宕机之后,状态为 StandBy 的 NameNode 能够主动顶上去;也就是故障的主动切换。如下图:
咱们这里应用了 Zookeeper 来监控 NameNode 状态,你能够了解当两个 NameNode 启动的时候,它们俩都会去抢这一把分布式锁,谁抢到了,谁的状态就是 Active,另外一个状态就是 StandBy。
这里其实还有一个要留神的点,就是如果 NameNode 过程宕机不存在了,Zookeeper 是能够感触到的,然而为什么还要引入 ZKFC 呢?这是因为有些状况 Zookeeper 不肯定能感触的到 NameNode 的,比方 NameNode 产生了 分钟级别的 FullGC,产生 FullGC 的时候,只有 GC 线程去运行的,咱们本地的工作线程是不运行的。
此时 NameNode 就不干活了,然而 ZKFC 是能够监控的到的,因为此时 NN 的过程还是在的,ZKFC 也会把这个事件通知给 ZK 的,这个时候 ZK 晓得过后,就会把这把锁给另外一个 NN,这样的话就实现了主备切换。
ZKFC 它会监控咱们的 NameNode,并且会把 NameNode 的监控状态报告给 Zookeeper(与 Zookeeper 放弃心跳)。
2)内存受限解决方案
下面说到随着业务越来越多,NameNode 的元数据越来越多就会导致 NameNode 内存不够用的问题。咱们能够想,如果是咱们事实中遇到这个问题了,咱们该怎么解决,大家能够看上面这个例子。
李四开了一家快递店,刚开始业务不是特地多,收的快递也不多,所以只须要一个仓库就能够放下这些快递了。可是随着双十一的到来,业务越来越多,收到的快递也越来越多,这个时候一个仓库曾经放不下这些快递了,这个时候如果你是李四,你会怎么办呢?最简略的方法就是一个仓库不够的话,咱们再建几个仓库就行了。
其实 NameNode 内存受限也是的,李四家的快递就相当于 NameNode 中的元数据,李四家的仓库就相当于 NameNode 的内存。当李四家的快递越来越多的时候,他的做法是再建几个仓库。那么当 NameNode 内存不够用的时候,咱们对应的解决方案就是再程度扩大几台 NameNode 机器,如下图的架构图:
这里要留神的是上图中互为联邦的两个 NameNode 它们存储的数据是不雷同的,因为这是当一台 NameNode 程度扩大的。就像李四家的一个仓库不够放快递了,他再建一个仓库放快递,那他这两个仓库放的快递必定不是一样的,比照到咱们互为联邦的 NameNode 这里也是一样的情理。其实咱们就是把 NameNode 扩大成了一个集群,像 DataNode 集群那样。
还有一个要留神的是上图中互为 HA 的两个 NameNode 所存储的数据是雷同的,因为这是为了解决 NameNode 单点故障的问题。
1.7 HDFS3
HDFS3 在架构上比照 HDFS2 没有大的扭转,就是 NameNode 高可用计划当中能够反对多个 NameNode,在 HDFS2 的 NameNode 高可用计划只能备份一个 NameNode,然而在 HDFS3 当中能够备份多个 NameNode。
HDFS3 还有一个扭转就是引入纠删码技术。
2. HDFS 反对亿级流量的明码
咱们来思考一个问题:
因为 NameNode 主节点治理了元数据,用户所有的操作申请都要操作 NameNode,大一点平台一天可能须要运行几十万、上百万的工作。咱们工作在运行的时候是须要一直的创立各种目录,各种文件,删除文件等,所以一个工作就会有多个申请,这些申请都写到 NameNode 这里去更新目录树。如果申请再多一点,那么对于 NameNode 来说就是亿级的流量,NameNode 是如何撑持亿级流量的呢?
2.1 NameNode 如何治理元数据
这是一台服务器,而后下面是咱们的内存,上面是咱们的磁盘,咱们能够认为这台服务器就是 NameNode。当咱们装置了 Hadoop 软件的时候,这个 NameNode 就是这样的一个状况。如下图:
当初咱们要启用 HDFS 的时候,咱们第一步首先要把磁盘进行格式化,就是咱们须要对这个文件系统进行格式化。比方咱们应用 Linux 操作系统的时候,要启用它的文件系统的时候也是须要格式化数据盘的。
对 HDFS 文件系统进行格式化过后在磁盘下面就会产生一个 fsimage 文件,而后咱们执行一个命令启动 NameNode 过程,而后就会把磁盘中的 fsimage 文件加载到内存外面。如下图:
当 fsimage 加载到内存外面当前,就会有申请一直的写到 内存的 fsimage。如果此时每天有一亿个申请写到内存的 fsimage 外面,这个时候 NameNode 是齐全能够扛得住的。因为一天一个亿的申请的话,一天 24 小时,均匀下来的话,这个 qps 也不算高的。所以在 NameNode 申请的纯内存操作是没有问题的。
然而这个架构设计是有问题的,不晓得小伙伴们能不能猜得到。这是因为咱们的申请如果只写 NameNode 内存的 fsimage 外面的话,当 NameNode 服务器宕机的话,这个时候内存外面的数据会失落的,这是不可取的。所以咱们的申请在写到内存的同时,还须要往磁盘外面写一份。这里往磁盘外面写并不是间接写磁盘,而是程序写磁盘下面的一个 editlog,这样的话能够放慢往磁盘写的速度。
这样的话,即便 NameNode 服务器宕机了,咱们也不必怕。咱们能够拿磁盘外面的 fsimage 和 多个 editlog 文件合并起来,从新加载一份新的元数据加载到内存外面就能够了。
其实申请还是会写一份到 JournalNode 集群外面的,这个咱们下面说过了,这是为了保障 NameNode 的高可用,咱们是通过 JournalNode 集群来同步数据到 Standby NameNode 的,所以咱们这个架构还会有 JournalNode 集群和 StandBy NameNode 服务器,如下图:
咱们把申请往 Active NameNode 的磁盘外面写是为了元数据的平安,往 JournalNode 集群外面写是为了 NameNode 的高可用。
其实咱们的 StandBy NameNode 会一直的从 JournalNode 集群去读取数据,而后每隔肯定的周期会把读取过去的数据在内存外面进行 checkpoint 造成新的 fsimage 文件,而后写到 StandBy NameNode 的磁盘外面。最好再拿 StandBy NameNode 磁盘外面的 fsimage 文件去替换 Active NameNode 磁盘外面的 fsimage 文件,如下图:
那么 StandBy NameNode 为什么要周期性的进行 checkpoint 操作生成新的 fsimage 文件,而后再替换 Active NameNode 外面的 fsimage 文件呢?这是因为当咱们的申请往 Active NameNode 内存写的时候,同时也会写到磁盘外面的 editlog 外面,随着申请越来越多 editlog 的个数就会越写越多。
如果这时候咱们重启了 Active NameNode 的时候,咱们须要从磁盘加载新的元数据到内存外面的时候,当 editlog 的个数越多,咱们加载的速度就越来越慢,有可能咱们重启一下 Active NameNode 会加载 5 – 6 分钟的元数据,这在生成环境是齐全不容许的。
如果咱们应用了 StandBy NameNode 去帮咱们实时合并 fsimage 文件的话,这样咱们 Active NameNode 磁盘外面的 editlog 文件个数就会变的很少,这样咱们启动 Active NameNode 在做数据回放的时候,效率就比拟高,Active NameNode 启动就十分快。
刚开始学习 HDFS 的时候,利用 StandBy NameNode 去定期做 fsimage 文件的合并的时候。我就在想,其实 Active NameNode 本人也能够定期做 checkpoint 去合并它服务器下面的 fsimage 和 editlog,然而为什么 HDFS 架构没有这样设计呢?
起初理解到是因为如果 Active NameNode 本人去做 元数据合并的话,为了数据安全,这个时候是须要对 Active NameNode 内存外面的这个 fsimage 去加锁的,因为如果不加锁的话,这个时候咱们申请还会往内存 fsimage 外面写的,而咱们同时又在合并 fsimage 外面的数据,这样数据就会的准确性就会呈现问题。
然而你一旦把 Active NameNode 内存外面的 fsimage 加锁的话,那么在 Active NameNode 做 checkpoint 合并元数据没有实现的时候,这把锁是不会开释的,这就会导致内存外面的 fsimage 不能接管来自内部的申请,这就意味着此时 Active NameNode 这段时间是不能对外提供服务的。
通过下面一步一步推理,咱们 NameNode 元数据管理的架构图就进去了,如下图:
然而此时还有一个问题,就是申请间接写到内存 fsimage 外面,它能够反对高并发,高可用,是十分快的。是能够抗住每天亿级流量的。然而这个申请同时还会写到 Active NameNode 和 JournalNode 磁盘外面,如下图:
咱们晓得往磁盘外面程序写的时候,速度还是能够的,然而往磁盘外面写是不反对高并发的,这是因为磁盘的物理个性和文件系统的限度。这个时候才是 HDFS 反对亿级流量的问题所在。
写内存的话,要想反对高并发,高性能这是十分好做的。然而往磁盘外面写,想要反对高并发和高性能这是十分艰难的。大家能够考虑一下 HDFS 在这一块怎么做的,下一篇文章我将通知大家 HDFS 在这一块怎么做的,这个设计也是 HDFS 元数据管理最精髓的局部。
另外 HDFS3 架构中的纠删码机制,我在下一张也会具体说一下到底是怎么回事。
最初大家能够扫码下方二维码,关注一下我的微信公众号。会不定期的更新大数据方面的文章,以及为大家发放各大编程等福利,如果有须要的能够关注一下。