HDFS
Hadoop基础之HDFS
什么是HDFS
- Hadoop Distributed File System
- hadoop的分布式文件系统
- 文件系统:
- 个人理解:在磁盘(只能做存储)的基础上,使用软件对所存储的内容进行管理的,这个软件就叫做文件系统
- 百度百科:文件系统是操作系统用于明确存储设备(常见的是磁盘,也有基于NAND Flash的固态硬盘)或分区上的文件的方法和数据结构;即在存储设备上组织文件的方法。操作系统中负责管理和存储文件信息的软件机构称为文件管理系统,简称文件系统。文件系统由三部分组成:文件系统的接口,对对象操纵和管理的软件集合,对象及属性。从系统角度来看,文件系统是对文件存储设备的空间进行组织和分配,负责文件存储并对存入的文件进行保护和检索的系统。具体地说,它负责为用户建立文件,存入、读出、修改、转储文件,控制文件的存取,当用户不再使用时撤销文件等。
分布式存储
- 对于一个容量超大的文件进行存储,在一个单独的位置很难完成,所以要按照某种规则,对这个文件进行切块,把每个块分别存储在集群中的不同节点里,分散了海量文件的存储压力
文件系统的表现形式
- 本地文件系统,普通操作系统里的文件系统
- windows: file:\\\C:\\ -- 盘符:\\路径
- linux: file:/// -- 根目录/路径
- 非本地文件系统,在操作系统之外的文件系统
- hdfs: hdfs://[ip:端口port]/路径
- ftp: ftp://
三个角色
- NameNode(NN)
- 集群领导者,全局唯一
- 任何节点都可以赋予NN角色
- 如果有其他机器配置了NN,其他机器会处于准备状态,如果此NN宕机,会顶替上来,但是,在同一时间只会有一个NN处于存活
- DataNode(DN)
- 工具人节点
- 存储真实数据
- 任何节点都可以赋予DN角色,一般不与NN和2NN在一起
- 为了保证数据的安全性和可靠性,数据在不同节点存三份
- SeondaryNameNode(2NN)
- 为了保证元数据的安全可靠,有2NN角色对NN进行备份
- 存储的数据与NN一样,定时与NN同步数据
- 为了保证数据的安全性,不与NN放置在同一节点,全局唯一
优缺点
- 优势
- 存储量大
- 可以容错,让数据更安全
- 适合一次写入,多次读出
- 劣势
- 速度慢
- 不适合做实时运算
- 可以添加,但是不可以修改(可以追加,但是不建议使用)
HDFS的存储方式
- 一个超大文件,按照128M为一个block块进行拆分,最后不足128M的部分自成一个block块
- 块大小
- 1版本是64M,2版本是128M
- 原因:最优化寻址时间
工作机制
- NameNode
- dfs/name/current所存储的元数据默认一个小时存储一次
- edits_0000000000000000001-000000000000000000N
- 这个文件的数值不是连续的
- 中间的数值间隔表示一个小时内所进行的操作的次数
- 查看方式:oev
- hdfs oev [-p xml] -i(input file) -o(output file)
- edits_inprogress文件存储的是当前正在进行的操作,他的编号是最大的,当此操作完成进行新操作,会将原本的文件重命名,然后重新创建一个新的文件用来保存当前正在进行的操作
- fsimage文件是edits文件和上一次inprogerss文件合并而来,只保存最近两个版本(镜像文件)
- 在fsimage在合并的时候,会首先将edits_inprogress保存成edits,并创建一个新的inprogress,然后将上一个fsimage和在它之后全部的edits合并在一起
- 合并工作由SecondaryNameNode来做
- fsimage.md5是fsimage的md5校验文件
- 查看方式:oiv
- hdfs oiv -p XML -i -o
- fsimage文件分为两部分
- 对文件和目录的单纯描述
- 根据文件或目录的ID赋予层次关系
- seen.txid这里保存的是当前inprogerss的id的最大值
- VERSION文件是默认生成的版本号
- 注意:造成日志滚动的的原因不仅仅是时间达到一个小时
- 强制滚动日志:hdfs dfsadmin -rollEdits
- 可以等到edits.inprogress满64M生成edits文件
- 操作数量达到一百万次会滚动
- 集群在启动、关闭时,会有日志滚动
- 手动滚动日志文件SecondoryNmeNode不改变,会在下一次自动同步的时候同步过去
- 手动合并: hdfs dfsadmin -saveNamespace -- 手动合并的时候需要在安全模式下进行
- 条件对应的配制项
- 时间周期
- dfs.namenode.checkpoint.period -- 默认3600
- 操作记录数
- dfs.namenode.checkpoint.txns -- 默认1000000
- 检查合并时间间隔
- dfs.namenode.checkpoint.chick.period -- 默认60
- HDFS开机启动NameNode过程
- 第一次启动namenode格式化后,创建HDFS镜像文件fsimage和编辑日志文件edits
- 每个block占元数据150byte
- 非第一次启动集群时
- namenode在启动的时候fsimage的内容会加载到内存中,然后执行editlog的各项操作,保证内存的元数据保持最新的
- 当上述操作完成后,创建新的edits文件和fsimage文件
- 同时产生新的edits.inprogerss
- 正常运行状态
- 当各节点都启动成功并且正常运行之后,HDFS中的更新都会写入到editlog中,不是直接写入fsimage中。
- 对于分布式系统而言,fsimage文件是非常庞大的,直接往fsimage文件写入数据效率非常低下,非常缓慢
- 相对而言,最大只有64MB大小的editlog文件,写入数据是十分高效的
- 启动时安全模式
- 在集群启动的过程中处于安全模式,此时只能读,不能取,当集群成功启动之后,系统会退出安全模式,开始对外进行完成服务支持
- DataName
- DataNode节点文件是存放真实数据的
- blk_xxx文件作为总文件的块文件,属于真实文件
- 路径中两层subdir0与我们的目录层次没有关系
- 工作原理
- DataNode在启动的时候向NameNode注册自己
- NameNode接收注册,把DataNode的数据信息记录下来,反馈回去
- DataNode每隔3秒钟与NameNode进行一次交互,目的为了证明当前DataNode可以使用
- 如果NameNode5分钟没有收到心跳,会主动寻找DataNode,达到两个周期(10分钟),没有找到则认为该节点不可用
- DataNode每隔一小时主动向NameNode报告一次,同步数据
- 断连超时时间计算公式
- TimeOut = 2*dfs.namenode.heartbeat.recheck[5min]-interval+10*dfs.heartbeat.interval[3s]
- HDFS写数据原理
- 客户端与NameNode发送连接请求,请求上传文件
- NameNode给客户端一个响应,可以上传文件
- 客户端分别对每个block块发送请求,请求存储数据的节点
- NameNode给客户端响应有可存储数据的节点
- 客户端与NameNode返回的所有节点建立连接
- 客户端把数据存储到每一个节点
- 客户端只将数据发送到一个节点
- 内部副本同步方式为集群内部传输
- 传输成功之后,再次请求NameNode,通知上传完毕
- NameNode保存相应的元数据信息
- HDFS读数据原理
- 客户端向NameNode请求下载文件
- NameNode向客户端返回这个文件的元数据
- 客户端根据获取的元数据,向具体的DataNode请求真实数据
- DataNode向客户端返回真实数据
- 所有block块获取完毕,在本地内存合并,写入文件
HDFS的安全模式
- 安全模式是HDFS处于一种特殊状态,这种状态下只能读不能改,换句话说,只能进行对数据不进行改变的操作
- 原因
- 当NameNode启动的时候,会将fsimage的数据加载到内存中,同时逐条执行editlog中的命令,在这期间,内存中成功建立文件系统元数据的映像后,就会创建一个新的fsimage文件和一个空的editlog文件
- 在这个过程中namenode是在安全模式下运行的,在安全模式中,DataNode会向NameNode发送块列表信息,当最小块副本满足的时候,NameNode会在三十秒后退出安全模式,开始提供完整服务
- 最小副本条件
- 整个文件系统中99.99%的块满足最小副本级别
- 系统离开安全模式的条件
- namenode收到DataNode的状态报告后确定
- 可用的block块占总数的比例
- 可用的数量节点满足要求
- 满足条件后维持的时间达到要求
- 可以用命令强制离开安全模式
- 安全模式的配制
- 安全模式主要配制在hdfs-site.xml
- 当没有额外配制的情况下,会采用默认值
- dfs.namenode.replication.min
- 最小的文件block副本数量,默认为1
- dfs.namenode.safemode.threshold-pct
- 副本数达到最小要求的block占系统总block数的百分比
- 只有实际比例大于默认比例,才能离开安全模式
- 如果小于等于0,则不会等待任何副本达到要求即可离开,如果大于1,永远处于安全模式
- dfs.namenode.safemode.extension
- 当条件满足后所需要维持的时间
- 如果在满足条件的情况下,同时所规定的时间内,没有出现不满足的情况下,即可离开安全模式
- 单位时毫秒
- 安全模式的命令
- hdfs dfsadmin -safemode[get/enter/leave/wait]
- get:查看是否处于安全模式
- enter:进入安全模式
- leave:退出安全模式
- wait:等待安全模式,让安全模式进入等待模式(适用于一直处于安全模式时,等待安全模式退出后执行)
HDFS脚本
- hadoop/hdfs
- hdfs dfs 等价于hadoop fs
- hadoop中包含但不限于hdfs命令,hdfs中只有dhfs命令
- hadoop/hdfs里面的每个命令都对应一个Java实现类
- [如果没有参数/参数为--help/参数为-help]--打印帮助信息
hdfs操作
- shell操作(通过命令直接操作文件系统)
- -help/--help/-h --获取帮助信息
- -ls --显示目录信息
- hdfs dfs -ls --显示目录信息
- -mkdir --创建目录
- hdfs dfs -mkdir [-p] 路径/目录名
- -moveFromLocal/-moveToLocat --从本地/hdfs剪切到hdfs/本地
- hdfs dfs -moveFromLocal/-moveToLocal 本地路径/hdfs路径 hdfs路径/本地路径
- -mv 在hdfs中移动文件
- -appendToFile --追加一个文件到文件末尾
- hdfs dfs -appendToFile 原文件 追加文件
- -cat --显示文件内容
- hdfs dfs -cat 文件名
- -tail --显示一个文件的末尾
- hdfs dfs -tail 文件名
- -chgrp/-chmod/-chown --修改文件权限
- hdfs dfs -chgrp/-chmod/-chown 权限类型(rwx) 文件/目录名
- -copyFromLocal/-copyToLocal --从本地/hdfs拷贝到hdfs/本地
- hdfs dfs -copyFromLocal/-copyToLocal 本地/hdfs hdfs/本地
- -cp --从一个hdfs的路径拷贝到另一个路径
- hdfs dfs -cp 原路径 目标路径
- -get --从hdfs下载文件到本地
- hdfs dfs -get 原文件 目标路径
- -getmerge --合并下载多个文件(可以理解为级联)
- hdfs dfs -getmerge 原目录 目标路径
- -put --等同于copyFromLocal
- hdfs dfs -put 本地 hdfs
- -rm --删除文件或目录
- hdfs dfs -rm 文件/路径
- -rmdir --删除空目录
- hdfs dfs -rmdir 目录
- -df --统计文件系统可用空间信息
- hdfs dfs -df -h
- -du --统计一个指定目录下的大小信息
- hdfs dfs -do -s -h 目录
- -ccount --统计一个指定目录下的文件节点数量
- hdfs dfs -count 路径
- -setrep --设置hdfs中文件的副本数量
- hdfs dfs -setrep [number] 路径(number数量要小于等于DataName节点数)
- hdfs dfs 原文件 目标文件
JavaAPI(通过开发工具写代码与HDFS连接)
- 构建项目的两种方式
- 普通方式,手动导包
- 查找依赖包hadoop.tar.gz解压缩 -->> share-hadoop搜索.jar
- 去除重名包、资源包、测试包
- 添加到项目中
- maven
- pom.xml添加所需要的依赖包的三点坐标
- 如果仓库中有需要的依赖包,可以添加
- 如果仓库中没有需要的依赖包,从网站中查找
- 代码
- 连接HDFS
<!-- package hdfs; import org.apache.hadoop.conf.Configuration; import org.apache.hadoop.fs.FileSystem; import org.apache.hadoop.fs.Path; import org.junit.jupiter.api.Test; import java.io.IOException; import java.net.URI; public class TestHdfsConnection { @Test public void connectionHdfs() throws Exception { Configuration configurations = new Configuration(); // 可以选择不写参数,然后再re目录下导入core-size.xml文件 // 如果没有core-size.xml的同时,Configuration也没有值,会走默认 // configurations.set("fs.default.name","hdfs://hadoop101:9000"); FileSystem fileSystem = FileSystem.get(new URI("hdfs://hadoop101:9000"),configurations,"bduser"); System.out.println(fileSystem); fileSystem.copyFromLocalFile(new Path("file:///D:/Tencent/QQManagementDate/461585949/FileRecv/第2章_彻底解决分布式一致性问题.pptx"),new Path("/home/bduser")); fileSystem.close(); } }
- 注意
- 设置属性的加载顺序
- xxx-default.xml
- xxx-size.xml
- 代码中conf.set(key,value)
- 生效顺序
- 与加载顺序相反
- 作用域
- default和site对于全局有效,conf.site只对当前方法有效
- 关于windows操作hdfs的权限问题
- 给更高权限
- 更改用户,使用当前所属者权限
- 解决方案
- hdfs dfs chmod o+w
- FileSystem.get(URI,conf,userName)
- run->editConfiguration->VM_options->-DHADOOP_USER_NAME=某某某
- 修改hdfs用户名与windows一致
- 修改windows用户名与hdfs一致
Hadoop集群间的复制
- scp:跨节点之间的数据复制
- 不管数据是否一致,都复制一遍,比较浪费资源
- rsync:跨节点之间的数据同步
- 两个节点之间相同目录下。不一样的数据进行同步
- hdfs dfs -cp:在一个集群之间进行数据的复制
- distcp:跨集群之间的数据复制
- hadoop distcp < srcurl> < desturl>
- 没有远程和本地的区别,双方都是远程集群,有的只是原路径和目标路径
- 复制文件和复制目录一样,没有特殊选项
- 如果为了保证安全,可以在目录后面加/*
小文件管理
- 容量小的文件,在hdfs中,不足128M都按照1289M计算
- 如果这样的文件过多的话,对hdfs来说就是灾难性的影响
- 解决方案
- 将多个小文件整合成一个文件来处理
- 创建存档
- hadoop archive -archiveName < name.har> -p < parent path> < src>*< dest>
- hadoop archive -archiveName 存档名字 -p 父目录 原路径(可以多个) 目的路径
- 执行创建存档之后,原文件不会自动删除,需要手动删除
- 查看存档
- hdfs dfs -lsr 路径
- 正常查看存档内容
- hdfs dfs -lsr har:///路径
- 查看存档内的所有内容
- hdfs dfs -cat 路径/part-x
- 查看存档具体内容
- 解除存档
- hdfs dfs -cp har:///路径/* 目标路径
配额管理
- 可以设置hdfs里目录存储的上限(数量和容量)
- 使用方式
- 设置数量限额
- hdfs dfsadmin -setQuota 数量 目录*
- 取消数量限额
- hdfs dfsadmin -clrQuota 目录*
- 设置容量限额
- hdfs dfsadmin -setSpaceQuota 容量 目录*
- 取消容量限额
- hdfs dfsadmin -clrSpaceQuota 目录*
如有问题,请发送邮件至buxiaqingcheng@163.com或者buxiaqingcheng@dingtalk.com