Hadoop环境搭建
hadoop分布式环境搭建
主要流程:
1、检查防火墙状态,若开启则关闭
2、免密设置
3、检查jdk安装
4、解压
5、配置环境变量(bin/sbin)并激活
6、配置hdfs (etc/hadoop)
hadoop-env.sh
core-site. xml
hdfs-site.xml
7、格式化namenode
创建tmp/ name tmp /data
执行hdfs namenode -format
8、配置yarn
yarn-site. xml
mapred-site.xml
9、配置完成,启动服务
start-dfs.sh
start-yarn.sh
HDFS架构原理
hdfs采用master/slave 架构
HDFS架构及各角色的作用:
client客户端
lunix window/shell COMMAND-LINE
java/scala/phython PROJECT
NameNode:
元数据节点
负责处理客户端的请求
DataNode:
数据节点:保存和Block检索
执行数据读写操作
secondary NameNode:
合并edit-log到fsimage中
赋值NameNode完成内存中元数据的持久化
hdfs副本机制
Block:数据块
HDFS最基本的存储单元
默认块大小:128M
副本机制:
作用:避免数据丢失
默认数:3
存放机制:
- 一个本地机架节点
- 一个同一机架不同节点
- 不同机架
HDFS的优缺点
优点:
高容错性(多备份)
yarn->datanode
yarn->appmaster->container
zookeeper(ha)->namenode
系统故障是不可避免的,如何做到故障之后的数据恢复和容错处理是至关重要的。
HDFS通过多方面保证数据的可靠性,多份复制并且分布到物理位置的不同服务器上,数据校验功能、后台的连续自检数据一致性功能都为高容错提供了可能。
数据量大
PB
流式访问
序列化,流传输
高吞吐量访问:HDFS的每个Block分布在不同的Rack上,在用户访问时,HDFS会计算使用最近和访问量最小的服务器给用户提供。 由于Block在不同的Rack上都有备份,所以不再是单数据访问,所以速度和效率是非常快的。另外HDFS可以并行从服务器集群中读写,增加了文件读写的访问带宽。
扩展成本低
增加集群机器的数量,可以是普通机器
缺点:
不适合低延时
IO操作频繁
不可以并发
没有事务,没有锁机制
不适用数据量小的文件
占空间(一个block默认128M),寻址慢(多nn分布在多个DataNode上
HDFS基本文件操作命令
1. 基本格式:hdfs dfs -cmd <args>
hadoop fs -cmd <args>(已过时)
2. 查看可用命令 hdfs dfs
- 上传文件
hdfs dfs -copyFromLocal test.sh /kb10
hdfs dfs -ls /kb10
- 查看hdfs文件内容
hdfs dfs -text /kb10/test.sh
- 从hdfs下载文件
hdfs dfs -get /kb10/test.sh
- 统计目录下文件大小
hdfs dfs -du /kb10/...
- 删除移动数据文件和目录文件
hdfs dfs -rm /kb10/...
hdfs dfs -rmr /kb10/...
hdfs dfs -rm -r /kb10/...
-创建多级目录
hdfs dfs -mkdir -p /hdfs/shell
HDFS Java 客户端操作
Maven创建
1.解压 hadoop 安装包到非中文路径(例如:
D:\users\hadoop-2.6.0-cdh5.14.2)。
2.在 windows 上配置 HADOOP_HOME 环境变量(与 windows 配置 jdk 环境变量
方法类似)
3.创建一个 Maven 工程 hadoop_day1201
(不用摸板创建)
4.导入相应的依赖,依赖如下:
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>cn.kgc</groupId>
<artifactId>hadoop_day1201</artifactId>
<version>1.0-SNAPSHOT</version>
<repositories>
<repository>
<id>cloudera</id>
<url>https://repository.cloudera.com/artifactory/cloudera-repos/</url>
</repository>
</repositories>
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>RELEASE</version>
</dependency>
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-core</artifactId>
<version>2.8.2</version>
</dependency>
<dependency>
<groupId>org.apache.hadoop</groupId>
<artifactId>hadoop-common</artifactId>
<version>2.6.0-cdh5.14.2</version>
</dependency>
<dependency>
<groupId>org.apache.hadoop</groupId>
<artifactId>hadoop-client</artifactId>
<version>2.6.0-cdh5.14.2</version>
</dependency>
<dependency>
<groupId>org.apache.hadoop</groupId>
<artifactId>hadoop-hdfs</artifactId>
<version>2.6.0-cdh5.14.2</version>
</dependency>
</dependencies>
</project>
5.创建包名:cn.kgc
6.创建 HdfsClientDemo类,使用 Junit 方式测试
1.创建文件
@Test
public void testMkdirs() throws Exception {
//获取文件系统
Configuration conf = new Configuration();
// conf.set("fs.defaultFS","hdfs://192.168.184.200:9000");
FileSystem fs = FileSystem.get(new URI("hdfs://192.168.184.200:9000"),conf,"root");
//创建一个文件夹
fs.mkdirs(new Path("/kb10/hdfs"));
//关闭资源
fs.close();
}
2.上传文件
@Test
public void testPutFileToHDFS() throws URISyntaxException, IOException, InterruptedException {
//获取文件系统链接
Configuration conf = new Configuration();
conf.set("dfs.replication","1");
FileSystem fs = FileSystem.get(new URI("hdfs://192.168.184.200:9000"), conf, "root");
//上传文件
fs.copyFromLocalFile(new Path("E:\\codes\\scala\\hadoop_day1201\\data\\HDFSClientDemo.java"),
new Path("/kb10/hdfs")
);
//关闭资源
fs.close();
}
3.下载文件
@Test
public void testGetFileToHDFS() throws URISyntaxException, IOException, InterruptedException {
//获取文件系统链接
Configuration conf = new Configuration();
conf.set("dfs.replication","1");
FileSystem fs = FileSystem.get(new URI("hdfs://192.168.184.200:9000"), conf, "root");
//下载文件
fs.copyToLocalFile(false,new Path("/kb10/test.sh"),
new Path("E:\\codes\\scala\\hadoop_day1201\\data"));
// fs.copyToLocalFile(true,new Path("/kb10/test.sh"),
// new Path("E:\\codes\\scala\\hadoop_day1201\\data"));
//关闭资源
fs.close();
}
4.查看目录内容
@Test
public void listFiles() throws URISyntaxException, IOException, InterruptedException {
//获取文件系统链接
Configuration conf = new Configuration();
conf.set("dfs.replication","1");
FileSystem fs = FileSystem.get(new URI("hdfs://192.168.184.200:9000"), conf, "root");
//获取文件信息
RemoteIterator<LocatedFileStatus> listFiles = fs.listFiles(new Path("/kb10"),true);
while(listFiles.hasNext()){
LocatedFileStatus status = listFiles.next();
System.out.println(status.getPath().getName());
System.out.println(status.getLen());
System.out.println(status.getReplication());
System.out.println(status.getGroup());
BlockLocation[] blockLocations = status.getBlockLocations();
for (BlockLocation blockLocation : blockLocations) {
System.out.println(blockLocation.getHosts());
System.out.println(blockLocation.getLength());
}
System.out.println("---------------------------");
}
//关闭资源
fs.close();
}
HDFS 读写流程
写:
1.client请求
client通过DFS向NN请求(写入文件存在)
2.NN 确认
目录存在、用户无操作权限return false
否则return true
3.client切分并请求第一个Block DN
client将文件切成n个128M的Block
client向NN请求第1个Block的存储DN列表
4.NN返回DN列表
假如返回: dn1 dn2 dn3
5.client写入
a.FSDOS向dn1请求写入
b.dn1请求dn2 ,dn2请求dn3,分别建立pipeline管道
c.dn3响应dn2 ,dn2响应dn1 ,dn1响应client
d.Block传输
d.1: client读取第一个Block并以Packet(64k)为单位传输, dn1每收到一个Packet会建立等待应答队列,
并逐级传输给dn2 ,dn3
d.2: dn3 , dn2 , dn1逐级应答,并将结果反馈给client
d.3:重复d.1~2直至Block传输完成
f.关闭FSDOS
6.client发送complete给NN。
7.重复3~6,直至所有Block传输完成
#读:
1.client创建DFS
DFs dfs = FileSystem.open()
2.DFS向NN请求RPC获取【文件开始部分】Block列表
列表按距离client的距离升序排序
每个Block包含DN地址,如果client就是DN,则本地读取
3.DFS向client返回支持文件定位的输入流对象FSDIS
FSDIS中包含一个(DFSIS)DFSInputStream,用来管理DN和NN之间的IO
如:DN中数据缺失,则可以通过DFSInputStream联系NN求助
NN借助YARN找到距离最近的另一个备份
4.client调用FSDIS的read()找到离client最近的DN,并连接DN
5.DFSIS依次读取一个批次的Block
a.读取包含文件第一个Block的最近DN地址
b.重复调用read()方法,直至第一个Block读取完成
c.关闭DN连接
d.重复a~c直至第一个批次的Block全部读取完成
6.重复2~5,直至所有批次的Block读取完成
7.关闭DFSIS,FSDIS,DFS