1,概念
HDFS有高容错性的特点,并且设计用来部署在低廉的(low-cost)硬件上;而且它提供高吞吐量(high throughput)来访问应用程序的数据,适合那些有着超大数据集(large data set)的应用程序。HDFS放宽了(relax)POSIX的要求,可以以流的形式访问(streaming access)文件系统中的数据。
HDFS 内部的所有通信都基于标准的 TCP/IP 协议。
1)场景:大数据存储
- 在多台计算机上的存储系统。
- HDFS中文件在物理上 是 分块存储( block 的 ,块的大小可以通过配置参数来规定,默认大小在 hadoop2.x 版本中是 128M 。
- HDFS 是设计成适应一次写入,多次读出的场景,且不支持文件的修改 。
2,架构:master/slave
hadoopV2版本及以后都是HA架构。以下为hadoop1架构,仅供学习。
Active NameNode:主节点
主 Master(只有一个),管理 HDFS 的名称空间,管理数据块映射信息;配置副本策略;处理客户端读写请求。
负责维护文件系统的名字空间 ,任何对文件系统名字空间或属性的修改都将被 Namenode 记录下来。
HDFS会给客户端提供一个 统一的抽象目录树 ,客户端通过路径来访问文件。
我们把 目录结构及文件分块位置信息 叫做 元数据 。 Namenode 负责维护整个hdfs 文件系统的目录树 结构 ,以及每一个文件所对应的 block 块信息( block 的id ,及所在的 datanode 服务器)。
Secondary NameNode
NameNode 的热备;定期合并 fsimage 和 fsedits,推送给 NameNode;当 Active NameNode 出现故障时,快速切换为新的 Active NameNode。
Datanode :从节点
Slave(有多个);存储实际的数据块;执行数据块读 / 写。
文件的各个block 的具体存储管理由 datanode 节点承担 。 每一个 block 都可以在多个 datanode 上 。 Datanode 需要定时向 Namenode 汇报自己持有的 block信息。存储多个副本(副本数量也可以通过参数设置dfs.replication ,默认是 3 )。
副本机制:为了容错,文件的所有block 都会有副本。
Client
与 NameNode 交互,获取文件位置信息;与 DataNode 交互,读取或者写入数据;管理 HDFS、访问 HDFS。
3,原理
存储原理
如果客户机想将文件写到 HDFS 上,首先需要将该文件缓存到本地的临时存储。如果缓存的数据大于所需的 HDFS 块大小,创建文件的请求将发送给 NameNode。NameNode 将以 DataNode 标识和目标块响应客户机。同时也通知将要保存文件块副本的 DataNode。当客户机开始将临时文件发送给第一个 DataNode 时,将立即通过管道方式将块内容转发给副本 DataNode。客户机也负责创建保存在相同 HDFS名称空间中的校验和(checksum)文件 。
在最后的文件块发送之后,NameNode 将文件创建提交到它的持久化元数据存储(在 EditLog 和 FsImage 文件)。
block块设置过小会出现什么问题?
- 存放大量小文件会占用NameNode中大量内存来存储元数据,而NameNode的内存是有限的,不可取;
- 文件块过小,寻址时间增大,导致程序一直在找block的开始位置。
因而,块适当设置的大一些,减少寻址时间,传输一个由多个块组成的文件的时间主要取决于磁盘的传输速率。一般设置为128M。
4,HA集群
概念
在一个典型的HA集群中,每个NameNode是一台独立的服务器。hadoopV2版本及以后都是HA架构。
单节点故障转移
主节点故障,从节点转为主节点。
hadoop1的不可靠在于可能存在单节点故障转移;
hadoop2.2.0(HA)中HDFS的高可靠指的是可以同时启动2个NameNode。其中一个处于工作状态,另一个处于随时待命状态。这样,当一个NameNode所在的服务器宕机时,可以在数据不丢失的情况下,手工或者自动切换到另一个NameNode提供服务。
脑裂
一个集群中多个管理者数据不一致。
多个NameNode之间共享数据,可以通过Nnetwork File System或者Quorum Journal Node以防止脑裂产生。前者是通过Linux共享的文件系统,属于操作系统的配置;后者是Hadoop自身的东西,属于软件的配置。
JournalNode Service
JournalNode服务器:运行的JournalNode进程非常轻量,可以部署在其他的服务器上。注意:必须允许至少3个节点。当然可以运行更多,但是必须是奇数个,如3、5、7、9个等等。当运行N个节点时,系统可以容忍至少(N-1)/2(N至少为3)个节点失败而不影响正常运行。
Primary NameNode、Standby NameNode
即 Active NameNode。
ha集群的任一时刻,只有一个NameNode处于active状态,另一个处于standby状态。其中,active状态的NameNode负责所有的客户端操作,standby状态的NameNode处于从属地位,维护着数据状态,随时准备切换。
在HA集群中,主从互换后,从节点变为主节点,主节点即使被拉起也会作为从节点。
在HA集群中,standby状态的NameNode可以完成checkpoint操作,因此没必要配置Secondary NameNode、CheckpointNode、BackupNode。如果真的配置了,还会报错。
如何解决启动多个NameNode时保证同一时刻只有一个NameNode工作 避免脑裂发生
使用Zookeeper完成高可用。
在HA集群中,如果zk与NameNode(active) 出现网络延迟这种情况时,zk会自动切换NameNode(standy) 为活跃节点,这个时候集群中就出现了多个NameNode active,进而出现脑裂问题。
Hadoop Journal Node可以解决脑裂问题,它有两个作用:
- 负责NameNode中edits同步
- 隔离机制。保证在这一时刻只能有一个NameNode active 使用ssh登录到NameNode节点上。
对于namenode是HA高可用集群时,客户端远程访问hdfs有两种实现方法
1> 将所有namenode ha相关的参数写入Configuration对象中
为了保证HDFS服务的高可用,生产环境是必须要开启NameNode HA的,此时应该用nameservices作为统一的logical name连接HDFS。
首先在Ambari UI上查看custom hdfs-site配置. 注意端口号要配成rpc的端口号(8020),而不能是http/https的。
import java.net.URI;
import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.fs.FileSystem;
import org.apache.hadoop.fs.Path;
public class HADemo {
public static void main(String[] args) {
// TODO Auto-generated method stub
Configuration conf = new Configuration();
conf.set("fs.defaultFS", "hdfs://HACluster");
conf.set("dfs.nameservices", "HACluster");
conf.set("dfs.ha.namenodes.HACluster", "nn1,nn2");
conf.set("dfs.namenode.rpc-address.HACluster.nn1", "namenode1_ip:8020");
conf.set("dfs.namenode.rpc-address.HACluster.nn2", "namenode2_ip:8020");
conf.set("dfs.client.failover.proxy.provider.HACluster",
"org.apache.hadoop.hdfs.server.namenode.ha.ConfiguredFailoverProxyProvider");
try {
FileSystem fs = FileSystem.get(new URI("hdfs://HACluster"), conf,"root");
boolean b=fs.mkdirs(new Path("/tmp/a"));
fs.copyFromLocalFile(new Path("D:\\test\\a.txt"), new Path("/tmp/a/a.txt"));
fs.close();
} catch (Exception e) {
System.out.println(e);
}
}
}
2> 将配置文件core-site.xml和hdfs-site.xml文件复制到项目的目录下
WebHDFS访问
通过WebHDFS访问HA集群时,就没有rpc方式那么方便了,有以下方式解决:
每次访问之前都从zookeeper中拿当前Active NameNode的地址
/**
* ͨ通过zookeeper获取active namenode地址
* @param ZOOKEEPER_IP ip地址
* @param ZOOKEEPER_PORT 端口
* @param ZOOKEEPER_TIMEOUT 超时时间
* @return 地址
*/
public static String getHostname(String ZOOKEEPER_IP, int ZOOKEEPER_PORT,
int ZOOKEEPER_TIMEOUT,String DATA_DIR) {
String hostname = null;
Watcher watcher = new Watcher() {
public void process(org.apache.zookeeper.WatchedEvent event) {
log.info("event:"+event.toString());
}
};
ZooKeeper zk = null;
byte[] data1 = null;
String[] iparr = ZOOKEEPER_IP.split(";");
for (String ip : iparr) {
try {
zk = new ZooKeeper(ip + ":" + ZOOKEEPER_PORT,
ZOOKEEPER_TIMEOUT, watcher);
data1 = zk.getData(DATA_DIR,
true, new Stat());
} catch (Exception e) {
// TODO Auto-generated catch block
log.info("This ip is not active..."+ip);
continue;
}
if (data1 != null) {
log.info("This ip is normal..."+ip);
ActiveNodeInfo activeNodeInfo=null;
try {
activeNodeInfo = HAZKInfoProtos.ActiveNodeInfo.parseFrom(data1);
} catch (InvalidProtocolBufferException e) {
// TODO Auto-generated catch block
log.error(e);
}
hostname = activeNodeInfo.getHostname();
return hostname;
}
}
return hostname;
}
每次访问轮询两个namenode
因为不确定主备节点哪个可以访问成功,那么每次轮询访问。
YARN ResourceManager HA
ResourceManager HA存在与NameNode HA类似的问题,能否通过统一的logical name访问RM的REST API呢? 答案是暂时不支持.
目前YARN只能支持standy RM把请求重定向到Active RM上. 也就是说假如主备RM都活着,当客户端向standby RM发HTTP请求时,standby RM会重定向到active RM上,但是如果standby RM不幸挂掉了,而Active RM还正常工作,此时请求就会失败.
解决方法其实也很简单,就是在调用RM REST API时轮询两个RM.
5,windows本地安装HDFS
1)操作环境
win10
jdk8
hadoop-3.1.3.tar.gz
apache-hadoop-3.1.3-winutils-master.zip
2)hadoop安装
- 下载并解压hadoop-3.1.3.tar.gz、apache-hadoop-3.1.3-winutils-master.zip
- 将hadoop-3.1.3放入指定目录:D:\software
- 将apache-hadoop-3.1.3-winutils-master中的文件:hadoop.dll、winutils.exe放入hadoop-3.1.3\bin目录下
- 配置环境变量:
环境变量名称 | 值 | 备注 |
---|---|---|
HADOOP_HOME | D:\software\hadoop-3.1.3 | |
Path | ;%HADOOP_HOME%\bin;%HADOOP_HOME%\sbin | |
JAVA_HOME | C:\Progra~1\Java\jdk1.8.0_221 | 注意一定要用波浪线代替Program Files,hadoop不能识别空格 |
- 配置数据目录
hadoop-3.1.3下新建data;data下新建:namenode,datanode - 进入etc/hadoop目录,修改配置文件
i>core-site.xml
<configuration>
<property>
<name>fs.default.name</name>
<value>hdfs://localhost:9000</value>
</property>
<property>
<name>hadoop.tmp.dir</name>
<value>/D://software//hadoop-3.1.3//data//temp</value>
</property>
</configuration>
ii>mapred-site.xml
<configuration>
<property>
<name>mapreduce.framework.name</name>
<value>yarn</value>
</property>
</configuration>
iii>yarn-site.xml
<configuration>
<!-- Site specific YARN configuration properties -->
<property>
<name>yarn.nodemanager.aux-services</name>
<value>mapreduce_shuffle</value>
</property>
<property>
<name>yarn.nodemanager.auxservices.mapreduce.shuffle.class</name>
<value>org.apache.hadoop.mapred.ShuffleHandler</value>
</property>
</configuration>
v>hdfs-site.xml
<configuration>
<!-- 这个参数设置为1,因为是单机版hadoop -->
<property>
<name>dfs.replication</name>
<value>1</value>
</property>
<property>
<name>dfs.permissions</name>
<value>false</value>
</property>
<property>
<name>dfs.namenode.name.dir</name>
<value>/D://software//hadoop-3.1.3//data//namenode</value>
</property>
<property>
<name>fs.checkpoint.dir</name>
<value>/D://software//hadoop-3.1.3//data//snn</value>
</property>
<property>
<name>fs.checkpoint.edits.dir</name>
<value>/D://software//hadoop-3.1.3//data//snn</value>
</property>
<property>
<name>dfs.datanode.data.dir</name>
<value>/D://software//hadoop-3.1.3//data//datanode</value>
</property>
</configuration>
- 配置hadoop使用的jdk
etc\hadoop\hadoop-env.cmd
set JAVA_HOME=%JAVA_HOME%
- cmd检测安装成功
java检测:java -version
hadoop检测:hadoop -version - 启动hadoop
双击:D:\software\hadoop-3.1.3\sbin\start-all.cmd - IDEA使用和调试
无需重启电脑,重启IDEA即可(×掉所有,重新打开;restart是不会生效的)。
要模拟linux,可设置目录:D:\opt… namenode\opt…