hdfs源于Google的GFS论文,是GFS的克隆版译为易于扩展的分布式文件系统,可以运行在大量的普通廉价机器上。hadoop,离线计算框架,数据很少会发生变化。当数据发生变化时,通过操作hdfs的方式进行数据同步,在hadoop中提供数据存储服务,具备数据管理功能/数据不丢失(冗余存储)。
hadoop进行数据运算时是以分布式的方式进行:任务分发 -> 资源调配 -> 结果同步,所以在对小数据量的处理时,从主观来看会感觉使用分布式计算反而比单机计算更慢,这是因为时间花费在了任务分发、结果同步上,;然而,当数据量足够大时,就能体现出分布式计算的优势了。
hdfs可以使得在数据计算时,数据的读取变得高效,提高计算的效率,同时可以作为多个数据计算框架数据存储支持,例如hive、hbase等。
如果一个集群中有100台节点:40台做数据存储,60台做数据运算
40台用于数据存储提升数据稳定性,例如使用商用固态硬盘/弹性块存储等高性能存储设备
60台应用于数据运算,需要提升提升CPU、内存性能
这100台节点都需要保证足够的带宽,否则带宽将会是这个集群分布式计算的瓶颈
使用流修改文件内容时,首先打开一个流,不断的读取文件信息,定位修改,通常不会直接修改
通常是以文件导入的方式将数据导入HDFS,将计算得到的数据(小数据量)进行读取,结果的展示
静态添加
停止集群,修改节点配置文件(slaves),启动集群
动态添加
在集群运行过程中进行变更,在新机器上配置好环境,同步各集群的hosts文件和slaves文件
在新节点中使用如下命令进行启动
sbin/hadoop-daemon.sh start datanode
sbin/yarn-daemon.sh start nodemanager
负责处理客户端的请求,元数据的查询和修改
启动过程
元数据管理
安全模式
一个新创建的集群不会进入安全模式,重新启动一个已有的集群,通常会有短暂的安全模式时间,用于完成合并和初始化的操作
hadoop dfsadmin -safemode get
hadoop dfsadmin -safemode wait
hadoop dfsadmin -safemode leave
hadoop dfsadmin -safemode enter
浏览器中输入地址SZ01:50070
可以在这个网页中查看集群信息等,也可以在上图的位置找到查看hdfs文件系统的页面,可以将hdfs中的文件下载至Windows本地;
在浏览器中直接下载文件时,传输数据的datanode是随机的,通常需要对每一台每一台机器配置hosts映射(Windows下),当机器数量较多时,可以手动修改主机名为IP,再重新发送请求。
两种命令格式:
hadoop fs -command path
hdfs dfs -command path
command为操作命令,上传、下载、删除、查看、移动、复制文件等,命令与Linux下的命令几乎相同
path为操作路径,hdfs根路径为hdfs://host:8020/,使用时可直接简写为/
hdfs也有绝对路径和相对路径,但一般使用时使用绝对路径,即从/开始
查看hdfs系统中存在的文件的命令:ls
hdfs dfs -ls path:查看path路径下的文件
hdfs dfs -lsr path = hdfs dfs -ls -R path:递归查看path路径下的文件
上传文件至hdfs命令:put(copyFromLocal)
hdfs dfs -put src(Linux文件系统) dest(HDFS文件系统)
hdfs dfs -put .bash_profile /
查看hdfs中文件内容:cat
hdfs dfs -cat file
hdfs dfs -cat /.bash_profile
从hdfs下载文件命令:get(copyToLocal)
hdfs dfs -get src(HDFS文件系统) dest(Linux文件系统)
hdfs dfs -get /.bash_profile /tmp
删除hdfs中文件、文件夹命令:rm rmdir
hdfs dfs -rm file:删除文件
hdfs dfs -rmdir emptyDir:删除空文件夹
hdfs dfs -rm -r notEmptyDir:删除非空文件夹
在hdfs-site.xml中配置了删除文件时并不是立即删除,而是现将文件移至某一文件夹,60分钟后彻底删除
hdfs dfs -rm /.bash_profile
创建文件夹:mkdir
hdfs dfs -mkdir dirPathName:指定路径和名字创建文件夹
hdfs dfs -mkdir /input
hdfs dfs -mkdir /output
hdfs dfs -mkdir test
移动文件(夹):mv
hdfs dfs -mv src(源) dest(目标)
hdfs dfs -mv /test.txt /s1/
复制文件(夹):cp
hdfs dfs -cp src(源) dest(目标)
hdfs dfs -cp /s1/test.txt /s1/s2/
更改文件(夹)权限:chmod
hdfs dfs -chmod [-R] xxx file(dir)
hdfs dfs -chmod 777 /s1/test.txt
在Windows下通过java操作服务器中的hdfs时,需要进行安装hadoop,配置环境变量,在项目中引入所需jar包,解决环境问题等操作
此工具可以直接执行某一个方法:不能有参数,不能有返回值
原理:调用无参的构造方法,再去调用声明测试的方法
使用方法:添加库,在要测试的方法前引入@Test注释,右键运行时选择JUnit Test
通常测试时只会指定一个方法进行测试
使用步骤:右键项目,build Path,configure Build Path,切换至Library,add Library,Junit
@Test
public void getHomeDir() {
//输出当前家目录
System.out.println(fs.getHomeDirectory());
}
Windows下配置hadoop
解决运行MapReduce时因环境而报错(为之后编写MapReduce代码做准备)
编写代码前,先将winutil.exe和hadoop.dll等文件拷贝至$HADOOP_HOME/bin目录下,并且将hadoop.dll拷贝至System32及SysWOW64目录下。双击运行winutil.exe,如果没报错即成功,如果报错,则需使用类库修复工具修复(具体可百度方法),完成后重启电脑
压缩包可从点击此处下载
新建java项目,在项目下新建文件夹lib
在hadoop解压目录下拷贝以下jar包粘贴至项目的lib文件夹中
$HADOOP_HOME/share/hadoop/common/hadoop-common-2.7.2.jar和hadoop-nfs-2.7.2.jar
$HADOOP_HOME/share/hadoop/common/lib中全部jar包$HADOOP_HOME/share/hadoop/hdfs/hadoop-hdfs-2.7.2.jar和hadoop-hdfs-nfs-2.7.2.jar
$HADOOP_HOME/share/hadoop/hdfs/lib中全部jar包
在eclipse中全选lib目录下的jar包,右键选择Build Path -> Add to Build Path(添加至构建路径)
将$HADOOP_HOME/etc/hadoop/log4j.properties拷贝至src根目录下
将第18行中hadoop.root.logger=INFO改成DEBUG,这样在运行项目后输出的信息会以debug信息输出,否则有些报错信息未能输出,不利于调试
import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.fs.FileSystem;
public class Test01 {
// 初始化配置对象
private static Configuration conf = new Configuration();
// 声明需要访问的集群地址
private final static String URI = "hdfs://SZ01:8020/";
// 声明操作文件系统的类
private static FileSystem fs;
static {
try {
// 从制定集群中读取配置
FileSystem.setDefaultUri(conf, URI);
// 使用读取到的配置实例化fs
fs = FileSystem.get(conf);
} catch (Exception e) {
e.printStackTrace();
}
}
public static void main(String[] args) {
// TODO 使用Java操作HDFS
// 输出默认的block块大小
System.out.println(fs.getDefaultBlockSize());
}
}
运行成功后输出结果为:
// 同时创建多级目录
public void mkdirs() {
try {
fs.mkdirs(new Path("t1/t2"));
fs.mkdirs(new Path("/s1/s2"));
} catch (IllegalArgumentException e) {
// TODO 自动生成的 catch 块
e.printStackTrace();
} catch (IOException e) {
// TODO 自动生成的 catch 块
e.printStackTrace();
}
}
上传文件通常是客户端通过web应用进行上传操作,将文件上传到linux本地磁盘,再上传至hdfs(指定删除源文件,指定不覆盖目标文件)
// 上传本地文件至hdfs
public void upLoad() {
try {
// 两个参数:本地文件路径和hdfs目录
fs.copyFromLocalFile(new Path("G://test/test.txt"), new Path("/"));
} catch (IllegalArgumentException e) {
// TODO 自动生成的 catch 块
e.printStackTrace();
} catch (IOException e) {
// TODO 自动生成的 catch 块
e.printStackTrace();
}
}
// 从hdfs下载文件至本地
public void downLoad() {
try {
fs.copyToLocalFile(false, new Path("/text.txt"), new Path("E://"), true);
} catch (IllegalArgumentException e) {
// TODO 自动生成的 catch 块
e.printStackTrace();
} catch (IOException e) {
// TODO 自动生成的 catch 块
e.printStackTrace();
}
}
import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.fs.FileSystem;
import org.apache.hadoop.fs.Path;
public class HDFSUtil {
/**
* 初始化工具类,指定需要操作的集群
* @param hostName
*/
public HDFSUtil(String hostName) {
URI = "hdfs://" + hostName + ":8020";
try {
// 将URI信息记录到配置项中
FileSystem.setDefaultUri(conf, URI);
// 使用读取到的配置实例化fs
fs = FileSystem.get(conf);
} catch (Exception e) {
e.printStackTrace();
}
}
// 初始化配置对象
private static Configuration conf = new Configuration();
// 声明需要访问的集群地址
private static String URI = "";
// 声明操作文件系统的类
private static FileSystem fs;
/**
* 返回当前用户的家目录
* @return
*/
public String getHomeDir() {
// 当前用户的家目录
return fs.getHomeDirectory().toString();
}
/**
* 创建文件夹
* @param path 完整路径,不需要添加斜杠
* @param useHomeDir 是否在用户家目录中创建
*/
public void mkdirs(String path, boolean useHomeDir) {
// 同时创建多级目录
try {
if (useHomeDir) {
fs.mkdirs(new Path(path));
} else {
fs.mkdirs(new Path("/" + path));
}
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* 文件上传
* @param delSrc 是否删除源文件
* @param overwrite 是否覆盖目标文件
* @param srcs 源文件路径,可以指定多个路径
* @param dest 目标路径
*/
public void upLoad(boolean delSrc, boolean overwrite, String[] srcs, String dest) {
try {
// fs.copyFromLocalFile(false, src, dst);
// 四个参数,是否删除源文件,是否覆盖目标文件,源路径,目标路径,声明不覆盖时抛出异常(不会发生覆盖)
// fs.copyFromLocalFile(false, false, new Path("E://test.txt"), new Path("/"));
// 上传单个文件时,直接上传
if (srcs.length == 1) {
fs.copyFromLocalFile(delSrc, overwrite, new Path(srcs[0]), new Path("/"));
} else {
// 上传多个文件时,生成所需的Path数组
Path[] paths = new Path[srcs.length];
for (int i = 0; i < srcs.length; i++) {
paths[i] = new Path(srcs[i]);
}
fs.copyFromLocalFile(delSrc, overwrite, paths, new Path("/"));
}
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* 文件下载
* @param delSrc 是否删除源文件
* @param src 源文件路径
* @param dest 目标路径
*/
public void downLoad(boolean delSrc,String src,String dest) {
try {
// 四个参数,是否删除源文件,源路径,目标路径,是否使用原生的系统文件系统
fs.copyToLocalFile(delSrc, new Path(src), new Path(dest), true);
} catch (Exception e) {
e.printStackTrace();
}
}
}
在集群中单台机器出现了误操作后导致系统不能正常运行,此时需要还原快照,如果没有快照则需重装系统。
还原快照后需要对三台机器的时间进行同步,否则hadoop集群无法进行正常工作。
同步时间的步骤:
所有机器切换至root用户
su - root
打开Xshell的发送键输入到所有会话的功能,输入以下命令
date -s ‘201x-xx-xx xx:xx:xx’
时间同步完成后,重启hadoop进程,即执行以下两步命令
stop-all.sh
start-all.sh
重启hadoop进程成功后,hadoop会对恢复快照的机器尝试自动检测和修复。
如果hadoop自动修复失败,即恢复快照的机器访问hdfs文件系统时跟其他机器访问hdfs所得到的结果不同,则需进行手动修复。
手动修复步骤:
损坏机器与正常机器都进入配置的datanode文件夹
cd hadoop/data/dfs/dn/current/BP-1387956734-192.168.128.121-1535966538843/current/finalized/subdir0/subdir0/
对比损坏机器与正常机器该目录下的文件情况,将正常机器多出来的文件复制到损坏的机器上,复制方式可以通过scp发送,或者Xftp先下载至本地再上传
手动修复后需要重启hadoop进程,此时修复完成。