大数据学习之 HDFS IO API的简单使用

12 篇文章 0 订阅
3 篇文章 0 订阅

HDFSIO流 API练习

import	java.io.FileOutputStream;
import	java.io.FileInputStream;
import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.fs.FSDataInputStream;
import org.apache.hadoop.fs.FSDataOutputStream;
import org.apache.hadoop.fs.FileSystem;
import org.apache.hadoop.fs.Path;
import org.apache.hadoop.io.IOUtils;
import org.junit.Test;
import java.io.IOException;
import java.net.URI;
import java.net.URISyntaxException;

/**HDFS IO流 API练习*/
public class HDFSIOTest {
    /**
     * 上传文件
     */
    @Test
    public void test1() throws URISyntaxException, IOException, InterruptedException {
        //创建配置文件信息
        Configuration conf = new Configuration();
        System.out.println("创建配置文件信息");
        //获取文件系统
        FileSystem filesystem = FileSystem.get(new URI("hdfs://bigdata2:9000"),conf,"root");
        System.out.println("获取文件系统");
        //创建输入流
        FileInputStream fis = new FileInputStream("C:\\Users\\wt\\Desktop\\yy\\3.doc");
        System.out.println("创建输入流");
        //输出路径和输出流
        Path path = new Path("hdfs://bigdata2:9000/aa.doc");
        FSDataOutputStream fos = filesystem.create(path);/*重点:filesystem.create(path)*/
        //对接两个流
        IOUtils.copyBytes(fis,fos,4*1024,true);
        System.out.println("上传成功");
    }
    /**
     * 下载文件
     */
    @Test
    public void test2() throws URISyntaxException, IOException, InterruptedException {
        //创建连接
        Configuration conf = new Configuration();
        System.out.println("创建配置文件信息");
        //获取文件系统
        FileSystem filesystem = FileSystem.get(new URI("hdfs://bigdata2:9000"),conf,"root");
        System.out.println("获取文件系统");
        //创建输出流
        FileOutputStream fos = new FileOutputStream("C:\\Users\\wt\\Desktop\\yy\\1.doc");
        System.out.println("创建输出流");
        //设定路径和输入流
        Path path = new Path("hdfs://bigdata2:9000/aa.doc");
        FSDataInputStream fis = filesystem.open(path);/*重点:filesystem.open*/
        System.out.println("设定路径和输入流");
        //流交换
        IOUtils.copyBytes(fis, fos,  1024, true);
        System.out.println("下载成功");
    }
    /**文件刷新,只有写入到hdfs中hflush操作才能将数据存储进去,不需要关闭也是能够查看到数据的*/
    @Test
    public void writeFile1() throws URISyntaxException, IOException, InterruptedException {
        //创建连接
        Configuration conf = new Configuration();
        System.out.println("创建配置文件信息");
        //获取文件系统
        FileSystem filesystem = FileSystem.get(conf);
        System.out.println("获取文件系统");
        //创建文件输出流
        Path path = new Path("/A.txt");
        FSDataOutputStream fos = filesystem.create(path);
        System.out.println("创建文件输出流");
        //写入数据
        fos.write("Hello World".getBytes());
        System.out.println("写入数据");
        //文件刷新,只有写入到hdfs中刷新操作才能将数据存储进去,不需要关闭也是能够查看到数据的
        //如果是windows的是无法在在关闭输出流之前查看的,刷新感觉是无效的
        fos.hflush();
        System.out.println("文件刷新");
        //关闭输出流
        fos.close();
        System.out.println("关闭输出流");
    }
    /**一致性模式,如果是往windows进行hflush是无效的*/
    @Test
    public void writeFile() throws Exception{
        // 1 创建配置信息对象
        Configuration configuration = new Configuration();
        FileSystem fs = FileSystem.get(configuration);

        // 2 创建文件输出流,并创建文件夹和文件
        Path path = new Path("F:\\date\\H.txt");
        FSDataOutputStream fos = fs.create(path);

        // 3 写数据
        fos.write("hello world".getBytes());
        // 4 一致性刷新
        fos.hflush();

        fos.close();
    }
}

HDFS四大机制

1、心跳机制

hdfs集群中namenode负责管理所有的datanode。
那namenode是如何管理的呢?
namenode怎么获取datanode存活状况的?
通过心跳策略获取的,datanode在集群运行的过程中会定期的向namenode发送自己的心跳报告,目的就是向namenoden报告自己的存活状况。
心跳报告的周期:hdfs-default.xml

<property>
<name>dfs.heartbeat.interval</name>
<value>3</value>
<description>Determines datanode heartbeat i
nterval in seconds.</description>
</property>

datanode每隔3s向namenode发送一个心跳报告(注意:心跳周期的单位是秒)。

如果一个datanode宕机了,namenode通过多长时间可以断定?
namenode连续10次接受不到datanode的心跳报告时,会认为当前的datanode可能宕机,默认设置如下:

<property>
<name>dfs.namenode.handler.count</name>
<value>10</value>
<description>The number of server threads for the namenode.</description>
</property>

这个时候namenode主动向datanode发送检查(后台守护进程)并等待检查的响应结果

<property>
<name>dfs.namenode.heartbeat.recheck-interval</name>
<value>300000</value>
<description>
This time decides the interval to check for expired datanodes.
With this value and dfs.heartbeat.interval, the interval of
deciding the datanode is stale or not is also calculated.
The unit of this configuration is millisecond.
</description>
</property>

namenode进行datanode的一次检查的时间300000ms=300s=5min,namenode这时候会主动检查两次,如果两次检查都没有响应,断定当前的datanode宕机了。因此,namenode断定一个datanode宕机的时间:103s+25min=10min30s

2、机架策略——副本存放策略

在hdfs中对于一个block默认的存储副本个数3个,这3个副本如何存放的?
三个副本分别存储在3个不同的节点上。事实上在实际生产的时候,节点在机架上的,所以,在存放副本时需考虑机架问题的副本存放策略如下:

1)第一个副本通常放在客户端所在节点(客户端是集群中的一个节点),如果客户端不是集群中的一个节点,则第一个副本上传到任意一个节点。

2)第二个副本放在和第一个副本相同机架的不同节点上,这个放在同一个机架的原因是为了备份速度更快。

3)第三个副本放在和第二个副不同机架的任意节点上。

实际生产中:副本存放有可能跨节点、跨机架、跨机房,甚至跨数据中心。

3、负载均衡

什么是负载均衡?
hdfs集群中的每一个datanode上的存储的数据和自己的硬件占比是相当的,这个时候我们可以认为这个hdfs集群是负载均衡的。集群的运行过程中,有可能造成集群中的从节点的负载不均衡,如果集群规模比较小的时候,集群有自动负载均衡的能力,集群自己在一段时间之后达到相对的负载均衡。

集群实现负载均衡的过程实际上就是数据块移动的过程(跨节点),因此可知负载均衡的带宽配置如下:

<property>
<name>dfs.datanode.balance.bandwidthPerSec</name>
<value>1048576</value>
<description>
Specifies the maximum amount of bandwidth that each datanode
can utilize for the balancing purpose in term of
the number of bytes per second.
</description>
</property>

默认集群负载均衡的带宽1M/s(很慢的),这个速度对于小规模集群还是可以满足的,但集群规模比较大的时候就不可以了,因为太慢了,集群规模大的时候就需要手动负载均衡。如何手动负载均衡呢?

1.start-balancer.sh -t 10% 这个命令不会立即执行,而是提升负载均衡的响应时效

2.调整带宽

<property>
<name>dfs.datanode.balance.bandwidthPerSec</name>
<value>1048576000</value>
<description>
Specifies the maximum amount of bandwidth that each datanode
can utilize for the balancing purpose in term of
the number of bytes per second.
</description>
</property>

/start-balancer.sh -t 10% 参数意义:datanode中最大的存储容量占比减去最小的存储的容量占比不超过10% 时认为是负载均衡的。如下:

hadoop01 2T 1T 50%

hadoop02 2T 1.1T 55%

hadoop03 2T 0.8T 40%

55%-40%=15%>10% 这时是负载不均衡的

4、安全模式

集群的安全模式是集群的一个自我保护的一种模式,在集群的安全模式下,不允许用户对集群进行部分操作的。

集群什么时候会进入安全模式?

1、集群启动的时候,集群会自己进入安全模式

启动顺序:
1namenode
2)datanode
3)secondarynamenode

启动namenode的时候做的事情:
namenode主要作用:
存储元数据,即
1)抽象目录树
2)数据和块的映射
3)数据块和节点的映射

元数据存储的位置:
1)硬盘上存储 /home/hadoop/data/hadoopdata/name/current
硬盘中的元数据包含:1) 2)但没有3)

2)内存中有全部的元数据

集群正常启动之后,读取的元数据信息都是内存中的,即包含1) 2) 3)

集群再启动namenode的时候:
1)将硬盘中的元数据加载到内存中

元数据信息:
hadoop-2.7.6.tar.gz 206M
1)/hadoop-2.7.6.tar.gz
2)hadoop-2.7.6.tar.gz:blk_12334:[] blk_12335:[]

启动datanode:
1)启动datanode的进程
2)启动完成向namenode进行发送心跳报告
3)datanode在发送心跳报告的时候也会发送块报告

namenode接受到这个块报告信息就会将相应的块id的节点放在元数据的相应位置,比如
hadoop-2.7.6.tar.gz:blk_12334:[hadoop01,hadoop02] blk_12335:[hadoop02,hadoop03]
启动secondarynamenode

集群在整个启动过程中处于安全模式,会进行一系列的检查,符合标准时才会离开安全模式:

1)检查每一个数据块的副本个数,每一个数据块的副本个数至少为1

<property>
<name>dfs.namenode.replication.min</name>
<value>1</value>
<description>Minimal block replication.
</description>
</property>

2)检查合乎标准的数据块占总数据块的比例

<property>
<name>dfs.namenode.safemode.threshold-pct</name>
<value>0.999f</value>
<description>
Specifies the percentage of blocks that should satisfy
the minimal replication requirement defined by dfs.namenode.replication.min.
Values less than or equal to 0 mean not to wait for any particular
percentage of blocks before exiting safemode.
Values greater than 1 will make safe mode permanent.
</description>
</property>

假设集群中的总的数据块的id:1000个
达到副本个数>=1的数据块的id:999 达标的数据块的比例999/1000=0.999
达到副本个数>=1的数据块的id:998 比例:0.998

3)检查存活的datanode个数

<property>
<name>dfs.namenode.safemode.min.datanodes</name>
<value>0</value>
<description>
Specifies the number of datanodes that must be considered alive
before the name node exits safemode.
Values less than or equal to 0 mean not to take the number of live
datanodes into account when deciding whether to remain in safe mode
during startup.
Values greater than the number of datanodes in the cluster
will make safe mode permanent.
</description>
</property>

至少保证0个datanode存活的

4)整个符合上面的标准的状态持续30s之后

<property>
<name>dfs.namenode.safemode.extension</name>
<value>30000</value>
<description>
Determines extension of safe mode in milliseconds
after the threshold level is reached.
</description>
</property>

保证集群的稳定性

集群启动过程中,为什么进入安全模式?
**
1)namenode将硬盘中的元数据加载到内存中
2)namenode接受datanode的心跳报告
3)namenode接受datanode的块报告
4)namenode会进行一系列的检查**

基于以上的原因,集群会进入安全模式,待上面的事情都完成的情况下,集群会自动退出安全模式。

2、集群运行过程中,也会进行检查
1)检查每一个数据块的副本个数,每一个数据块的副本个数至少为1

<property>
<name>dfs.namenode.replication.min</name>
<value>1</value>
<description>Minimal block replication.
</description>
</property>

2)检查合乎标准的数据块占总数据块的比例

<property>
<name>dfs.namenode.safemode.threshold-pct</name>
<value>0.999f</value>
<description>
Specifies the percentage of blocks that should satisfy
the minimal replication requirement defined by dfs.namenode.replication.min.
Values less than or equal to 0 mean not to wait for any particular
percentage of blocks before exiting safemode.
Values greater than 1 will make safe mode permanent.
</description>
</property>

假设集群中的总的数据块的id:1000个
达到副本个数>=1的数据块的id:999 达标的数据块的比例999/1000=0.999
达到副本个数>=1的数据块的id:998 比例:0.998
检查的时候发现不符合要求,也会自动进入安全模式。

3.如果集群处于维护或者是系统升级时可手动进入安全模式,命令:

hdfs dfsadmin -safemode get 获取当前集群的安全模式状态
Safe mode is OFF 离开了安全模式
Safe mode is ON 在安全模式
hdfs dfsadmin -safemode leave 强制离开安全模式
hdfs dfsadmin -safemode enter 强制进入安全模式
hdfs dfsadmin -safemode wait 等待安全模式自行离开(没有意义)

在安全模式下,可以执行的操作,和不可以执行的操作?
可以执行的操作:ls、get、cat、tail
不可以执行的操作:-put、-mkdir、-touchz、-appendToFile、-rm

此处参考链接:https://blog.csdn.net/qq_1018944104/article/details/84994222

HDFS写入与下载

写入数据:
上传
1)客户端向namenode请求上传文件,namenode检查目标文件是否已存在,父目录是否存在。
2)namenode返回是否可以上传。
3)客户端请求第一个 block上传到哪几个datanode服务器上。
4)namenode返回3个datanode节点,分别为dn1、dn2、dn3。
5)客户端请求dn1上传数据,dn1收到请求会继续调用dn2,然后dn2调用dn3,将这个通信管道建立完成
6)dn1、dn2、dn3逐级应答客户端
7)客户端开始往dn1上传第一个block(先从磁盘读取数据放到一个本地内存缓存),以packet为单位,dn1收到一个packet就会传给dn2,dn2传给dn3;dn1每传一个packet会放入一个应答队列等待应答
8)当一个block传输完成之后,客户端再次请求namenode上传第二个block的服务器。(重复执行3-7步)

下载数据:
读数据
1)客户端向namenode请求下载文件,namenode通过查询元数据,找到文件块所在的datanode地址。
2)挑选一台datanode(就近原则,然后随机)服务器,请求读取数据。
3)datanode开始传输数据给客户端(从磁盘里面读取数据放入流,以packet为单位来做校验)。
4)客户端以packet为单位接收,先在本地缓存,然后写入目标文件

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值