HDFS Architecture
1.为什么说HDFS不擅长存储小文件?
因为Namenode是使用单机存储元数据,因此导致namenode内存紧张
HDFS使用于高吞吐量,不适合低时间的延迟访问,如果同时存储大量的小文件会花费大量的时间
namenode 访问小文件,从一个datanode跳转到另外一个datanode,这样大大降低了读取性能。
2.NameNode和Secondary Namenode的关系?
fsimage - 它是在NameNode启动时对整个文件系统的快照
edit logs - 它是在NameNode启动后,对文件系统的改动序列,相当与日志
只有在NameNode重启时,edit logs才会合并到fsimage文件中,从而得到一个文件系统的最新快照。但是在产品集群中NameNode是很少重启的,这也意味着当NameNode运行了很长时间后,edit logs文件会变得很大
如果NameNode挂掉了,那我们就丢失了很多改动因为此时的fsimage文件非常旧,因此为了克服这个问题,我们需要一个易于管理的机制来帮助我们减小edit logs文件的大小和得到一个最新的fsimage文件,这样也会减小在NameNode上的压力。这跟Windows的恢复点是非常像的,Windows的恢复点机制允许我们对OS进行快照,这样当系统发生问题时,我们能够回滚到最新的一次恢复点上。
SecondaryNameNode就是来帮助解决上述问题的,辅助NameNode整理Edits和Fsimage文件,加速NameNode启动过程.
Secondary NameNode的整个目的是在HDFS中提供一个检查点。它只是NameNode的一个助手节点。这也是它在社区内被认为是检查点节点的原因。
3.HDFS Shell*
[root@CentOS ~]# hdfs dfs -appendToFile /root/install.log /aa.log #追加
[root@CentOS ~]# hadoop fs -cat /aa.log #查看指定文件输出的内容
[root@CentOS ~]# hdfs dfs -checksum /aa.log
/aa.log MD5-of-0MD5-of-512CRC32C 000002000000000000000000fa622ce196be3efd11475d6b55af76d2
[root@CentOS ~]# hadoop fs -chmod -R u+x /# 改变文件的权限
[root@CentOS ~]# hadoop fs -ls -R / #查看文件
-rwxr--r-- 1 root supergroup 17630 2019-01-03 09:05 /aa.log
-rwxr--r-- 1 root supergroup 175262413 2019-01-02 20:29 /jdk-8u171-linux-x64.rpm
[root@CentOS ~]# hdfs dfs -copyFromLocal|-put install.log / # 上传
[root@CentOS ~]# hdfs dfs -copyToLocal|-get /install.log ~/ # 下载
[root@CentOS ~]# hdfs dfs -mkdir -p /demo/dir #将文件从源路径复制到目标路径
[root@CentOS ~]# hdfs dfs -cp /install.log /demo/dir
[root@CentOS ~]# hdfs dfs -moveFromLocal ~/install.log /
[root@CentOS ~]# ls
anaconda-ks.cfg hadoop-2.6.0_x64.tar.gz install.log.syslog
[root@CentOS ~]# hdfs dfs -moveToLocal /install.log ~/ # 目前还没有实现
moveToLocal: Option '-moveToLocal' is not implemented yet.
[root@CentOS ~]# hdfs dfs -rm -r -f /install.log #删除
[root@CentOS ~]# hdfs dfs -text /cc.log #将文件尾部1k字节内容输出
[root@CentOS ~]# hdfs dfs -touchz /cc.log #创建空文件
开启 HDFS 的回收站
`etc/hadoop/core-site.xml
`
<property>
<name>fs.trash.interval</name>
<value>1</value>
</property>
[root@CentOS ~]# hdfs dfs -rm -r -f /bb.log
19/01/03 12:27:08 INFO fs.TrashPolicyDefault: Namenode trash configuration: Deletion interval = 1 minutes, Emptier interval = 0 minutes.
Moved: 'hdfs://CentOS:9000/bb.log' to trash at: hdfs://CentOS:9000/user/root/.Trash/Current
[root@CentOS ~]# hdfs dfs -rm -r -f -skipTrash /aa.log
Deleted /aa.log
5.JAVA API 操作 HDFS
<dependency>
<groupId>org.apache.hadoop</groupId>
<artifactId>hadoop-hdfs</artifactId>
<version>2.6.0</version>
</dependency>
<dependency>
<groupId>org.apache.hadoop</groupId>
<artifactId>hadoop-common</artifactId>
<version>2.6.0</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
</dependency>
Windows开发Hadoop应用环境配置
-
解压hadoop安装包到
C:/
-
将
winutils.exe
和hadoop.dll
拷贝到hadoop的bin目录下 -
在windows配置HADOOP_HOME环境变量
-
重启开发工具
idea
,否则开发工具无法识别HADOOP_HOME -
在Windows主机配置CentOS的主机名和IP的映射关系
C:\Windows\System32\drivers\etc\hosts
192.168.169.139 CentOS
core-site.xml和hdfs-site.xml放到resources下
import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.fs.*;
import org.apache.hadoop.io.IOUtils;
import org.apache.hadoop.util.Progressable;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import static org.junit.Assert.*;
import java.io.*;
public class TestHDFSDemo {
private FileSystem fileSystem;
private Configuration conf;
@Before
public void before() throws IOException {
conf=new Configuration();
conf.addResource("core-site.xml");
conf.addResource("hdfs-site.xml");
fileSystem=FileSystem.newInstance(conf);
}
@Test
public void testConfig(){
String value = conf.get("dfs.replication");
System.out.println(value);
}
@Test
public void testUpload01() throws IOException {
String file="C:\\Users\\HIAPAD\\Desktop\\SpringBoot启动原理.pdf";
Path dst=new Path("/demo/access/springBoot.pdf");
InputStream is = new FileInputStream(file);
OutputStream os = fileSystem.create(dst, new Progressable() {
public void progress() {
System.out.print(".");
}
});
IOUtils.copyBytes(is,os,1024,true);
}
@Test
public void testUpload02() throws IOException {
Path src=new Path("C:\\Users\\HIAPAD\\Desktop\\SpringBoot启动原理.pdf");
Path dst=new Path("/springBoot1.pdf");
fileSystem.copyFromLocalFile(src,dst);
}
@Test
public void testDownload01() throws IOException {
String file="C:\\Users\\HIAPAD\\Desktop\\SpringBoot启动原理1.pdf";
Path dst=new Path("/springBoot.pdf");
OutputStream os = new FileOutputStream(file);
InputStream is = fileSystem.open(dst);
IOUtils.copyBytes(is,os,1024,true);
}
@Test
public void testDownload02() throws IOException {
Path dst=new Path("C:\\Users\\HIAPAD\\Desktop\\SpringBoot启动原理3.pdf");
Path src=new Path("/springBoot1.pdf");
//fileSystem.copyToLocalFile(src,dst);
fileSystem.copyToLocalFile(false,src,dst,true);
}
@Test
public void testDelete() throws IOException {
Path src=new Path("/user");
fileSystem.delete(src,true);//true 表示递归删除子文件夹
}
@Test
public void testExists() throws IOException {
Path src=new Path("/springBoot1.pdf");
boolean exists = fileSystem.exists(src);
assertTrue(exists);
}
@Test
public void testMkdir() throws IOException {
Path src=new Path("/demo/access");
boolean exists = fileSystem.exists(src);
if(!exists){
fileSystem.mkdirs(src);
}
}
@Test
public void testListFiles() throws IOException {
Path src=new Path("/");
RemoteIterator<LocatedFileStatus> files = fileSystem.listFiles(src, true);
while (files.hasNext()){
LocatedFileStatus file = files.next();
System.out.println(file.getPath()+" "+file.isFile()+" "+file.getLen());
BlockLocation[] locations = file.getBlockLocations();
for (BlockLocation location : locations) {
System.out.println("offset:"+location.getOffset()+",length:"+location.getLength());
}
}
}
@Test
public void testDeleteWithTrash() throws IOException {
Trash trash=new Trash(fileSystem,conf);
Path dst=new Path("/springBoot1.pdf");
trash.moveToTrash(dst);
}
@After
public void after() throws IOException {
fileSystem.close();
}
}
HDFS权限不足导致写失败?
org.apache.hadoop.security.AccessControlException: Permission denied: user=HIAPAD, access=WRITE, inode="/":root:supergroup:drwxr-xr-x
at org.apache.hadoop.hdfs.server.namenode.FSPermissionChecker.checkFsPermission(FSPermissionChecker.java:271)
at org.apache.hadoop.hdfs.server.namenode.FSPermissionChecker.check(FSPermissionChecker.java:257)
解决方案
方案1
etc/hadoop/hdfs-site.xml
<property>
<name>dfs.permissions.enabled</name>
<value>false</value>
</property>
关闭HDFS文件权限检查,修改完成后,重启HDFS服务
-DHADOOP_USER_NAME=root 就是设置JAVA虚拟机启动参数java XXX -Dxx=xxx