HDFS
HDFS 是一种典型的分布式文件系统,但其不是唯一的分布式文件系统
HDFS 是一种新型的文件系统,不同于传统的文件系统,新型文件系统解决了传统文件系统存在的负载不均衡与网络瓶颈问题。
但归根结底、这些弊端都是由传统文件系统所存在的文件存储大小不均衡造成的:文件在拆分时导致某些磁盘利用率过高等等
注意:HDFS 选择使用 块机制 来解决这个问题,HDFS 中,每个块的大小为 128 MB
HDFS 中的块
我们在寻找分布式系统中的某一个文件时,会先在 NameNode 中寻找文件切开的块的位置和数量,再根据这些索引将文件取出来,故而如果将块分的太小,就会极大的增加寻址时间,这样会极大的降低效率。
元数据:每一个文件的名称、大小、存储位置等信息的合集,叫做元数据
另外,这个 HDFS 中的块也是可以配置的,我们进入 HADOOP 环境中的 share 目录中,这个目录中的文件都是 hadoop 中的配置信息
share 中的配置都是默认配置,我们在自行配置的时候一般在:core-site.xml、hdfs-site.xml、mapred-site.xml、yarn-site.xml 四个文件中进行自己的自定义配置,hadoop 会先加载自己的默认配置,后加载自行添加的配置,这就会导致我们自行添加的配置将 hadoop 的配置覆盖掉,从而实现手动配置
首先将配置文件拷贝到 家 目录下
# 在 hadoop 的 share 目录下执行下面的操作:将目录中所有匹配的文件复制到 ~ 的根目录下
find -name "*-default.xml" -exec cp {} ~ \;
记得整理一下,创建一个新文件夹并将其全部移动到里面:
mkdir ...
mv *-default.xml ./default-conf
下面是一些配置文件的示例:
# hdfs-default.xml
# 这里的 dfs.blocksize 属性就代表 HDFS 中的块大小
<property>
<name>dfs.blocksize</name>
<value>134217728</value> # 这里单位是字节
<description>
The default block size for new files, in bytes.
You can use the following suffix (case insensitive):
k(kilo), m(mega), g(giga), t(tera), p(peta), e(exa) to specify the size (such as 128k, 512m, 1g, etc.),
Or provide complete size in bytes (such as 134217728 for 128 MB).
</description>
</property>
# 这里是块的存放位置,默认可以在 hdfs-site.xml 中找
<property>
<name>dfs.datanode.data.dir</name>
<value>file://${hadoop.tmp.dir}/dfs/data</value>
<description>Determines where on the local filesystem an DFS data node
should store its blocks. If this is a comma-delimited
list of directories, then data will be stored in all named
directories, typically on different devices. The directories should be tagged
with corresponding storage types ([SSD]/[DISK]/[ARCHIVE]/[RAM_DISK]) for HDFS
storage policies. The default storage type will be DISK if the directory does
not have a storage type tagged explicitly. Directories that do not exist will
be created if local filesystem permission allows.
</description>
</property>
HDFS 优点:
- 一个文件具有多个副本,具有高稳定性
- 适合做大数据集:GB、PB、TB 级的数据
- 一次性写入、多次读取;保证数据的一致性与安全性
- 构建成本低:可以构建在廉价机器上
- 基于 JAVA、多平台可移植
- 在多节点中动态的移动数据,以保证各节点的平衡
- Hadoop 具有可靠的存储与处理数据的能力
HDFS 缺点:
- HDFS 设计的初衷是处理大型数据集,其不适合做低延迟的数据处理
- 不适合小文件存取 找到小文件所需要的寻址时间十分长
- 不支持多用户对同一文件的写操作
HDFS体系结构
HDFS 采用主从结构来管理数据,该结构模型由四个部分组成:Client(客户端 )/ NameNode (名称节点)/ DataNode(数据节点) / SecondaryNameNode
其中 一个真正的 HDFS 集群主要包括一个 Namenode 和若干个 Datanode
其中 Namenode 主要负责管理统筹,Namenode 中维护着一个目录树用来记录 HDFS 中文件存储的结构,另外,其中还有 Namespace,Namespace维护着Datanode中文件的信息(某个文件存储在哪几个块中等),此外其也维护着文件名、权限、最后修改时间等信息,另外,其也持久化了 fsimage 和 edit 用于备份,防止数据丢失。
数据块中的数据是保存在 Linux 系统本地的,Datanode 在 Namenode 的统筹下进行数据块的创建、删除、复制等操作,而 Datanode 会定期向Namenode中发送数据(心跳数据包(间隔 3 秒)),用于向Namenode证明自己的存活性,对于长时间没有发送心跳包的节点,Namenode会将其判定为宕机,不对其分配 存储、修改、删除等操作
同时,Namenode也负责客户端的访问
fsimage 与 edit
fsimage 是映像文件,可以当做是系统目录的一个实时镜像,其会每间隔一段时间进行拍摄,edit log 相当于在镜像基础上的一个操作日志,其记录了镜像在拍摄之后的操作记录。
这样当我们发生宕机时,就可以利用 fsimage 先拉取一个镜像,再加载 edit log 来完全恢复宕机之前的状态
集群的启动过程
集群启动时内存为空,Namenode 会根据 fsimage 和 edit log 加载内容,加载完成后,Datanode 为安全模式,此时不能进行任何的操作,等待 Datanode 心跳包传入 99.9% 时,进入正常模式,开始正常操作
edit log 会在
- 手动滚动
- 正在写入的 editlog 大小满 64M
- 操作到达 100 万次
- 设定的时间到了(默认一小时)
时滚动一次,也就是创建新的 edit log
而:fsimage 会在
- Namenode 启动并加载镜像文件与编辑日志时产生
- SecondaryNamenode 生成的 fsimage.checkpoint 替换 fsimage 时重新生成
心跳机制
HDFS 中的 Namenode 不会因为一次两次没有收到心跳包就判定其死亡,而是会在两次重试时间(默认5分钟)和10 次心跳接收时间(每次 3 秒)后再被判定为宕机
Secondary 的主要作用是辅助 Namenode 进行 fsimage 和 edit log 的结合,加快安全模式的退出,提高程序运行效率
在触发检查点机制后(事物操作达到 100 W 次、edit log 大小达到 64M、edit 时间达到了 1 小时)
- Secondarynamenode请求 Namenode 停止当前正在使用的 edit log
- Secondarynamenode 创建新的 edit log 给Namenode使用
- Secondarynamenode 通过 HTTP 协议获取最新的 fsimage 和刚刚停止的 edit log
- Secondarynamenode 对 fsimage 和 edit log 进行合并,最终生成一个 fsimage.ckpt 文件(示例:fsimage_56.ckpt),也就是通过检查点机制新创建的 fsimage 文件,将这个文件通过 HTTP 协议传给 Namenode,Namenode 将这个文件更名为 fsimage_56,也就是去掉检查点后缀,之后当做最新的 fsimage 文件使用
HDFS 读数据
- HDFS Client 发送读数据的请求(通过 open() 创建一个 DistributeInputStream):
- Namenode 根据 HDFS Client 提供的文件在对应的目录树位置找到合适的位置,判断该位置是否存在对应的文件,以及判断用户是否有权限获取该文件
- Namenode 会返回目标文件的元数据,并作为一个FSDataInputStream 对象返回 此处注意:这个对象包含以下信息:目标文件的所有块的位置,以及每个块分布在的 Datanode,并按照能够最快获取 Datanode 的速度进行排序,以让 HDFS Client 能够在一开始就获取到能够最快获取所有文件的速度。
- HDFS Client 会找到对应的 Datanode 并从中读取数据,将读到的数据返回给本地文件,并依次将读到的块中的内容向文件的末尾添加。
若在读取文件时 datanode 发生错误的情况,则会选取第二个备份的机器中搜寻对应的 内容
HDFS 写数据
- HDFS Client 先对需要上传的文件进行切块
- HDFS Client 调用 create() 方法 创建一个 DistributeFileSystem 对象,向 Namenode 请求创建文件
- Namenode 对文件进行检查,检查文件是否在当前目录存在以及对象是否在当前目录下具有上传的权限,若都成功,则会返回一个 FSDataOutputStream
- HDFS Client 利用这个 FSDataOutputStream 进行写入,同时的,Namenode 根据集群中心选出距离最近的三个 Datanode 机器
- HDFS Client 与最近的 Datanode 建立 pipeline 管道连接,Datanode 再与下一个需要保存副本的 Datanode 建立连接
- 之后进行数据发送,每次发送结束每个节点都会返回一个收到信息
- 发送完毕后,关闭所有管道
客户端是看不到正在写的块的