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

本文详细介绍了HDFS的心跳机制,包括datanode定期向namenode发送心跳报告以报告其存活状态,以及namenode如何判断datanode宕机。此外,还探讨了HDFS的副本存放策略,解释了如何按照机架策略存储数据块,以确保备份速度和数据安全性。最后,简要提到了HDFS的负载均衡和安全模式的概念。

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.youkuaiyun.com/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为单位接收,先在本地缓存,然后写入目标文件

<think>首先,用户的问题是关于使用JavaAPI操作HDFS并获取客户端对象的示例或教程。他们引用了几个站内引用,这些引用似乎来自之前的回答或文档,涉及JavaAPI操作HDFS的具体代码片段。用户的关键点是:“我想查找如何使用JavaAPI操作HDFS并获取客户端对象的示例或教程请问使用JavaAPI操作HDFS获取客户端对象示例代码或学习案例”我需要基于系统级指令来构建回答:-使用中文回答。-结构清晰,逐步解决问题。-保证回答真实可靠。-在行内数学表达式使用$...$,独立公式使用$$...$$,但由于这是一个编程主题,可能数学表达式不多,但如果有的话,要正确处理。-生成相关问题。-在引用的段落末尾添加引用标识。从提供的引用中:-引用[1]:提到在Java项目中创建Configuration和FileSystem对象来操作HDFS-引用[2]:展示了使用@Test注解测试mkdir操作,涉及FileSystem对象。-引用[3]:给出了一个完整的Java示例代码,用于上传文件到HDFS,包括创建Configuration和FileSystem对象。用户的核心需求是“获取客户端对象”,在Hadoop中,这通常指的是FileSystem对象,它是客户端API的核心。我的回答应该:1.解释如何获取HDFS的客户端对象(即FileSystem对象)。2.提供示例代码。3.参考站内引用,确保真实可靠。4.结构清晰,比如分步骤。5.在末尾生成相关问题。结构:-开头简要介绍。-逐步讲解步骤:a.设置Configuration对象。b.获取FileSystem对象。c.使用对象进行操作。-提供完整代码示例。-添加引用标识。-最后生成相关问题。示例代码基于引用[3],但需要确保正确性。引用[3]中的代码是:```javaimportorg.apache.hadoop.conf.Configuration;importorg.apache.hadoop.fs.FileSystem;importorg.apache.hadoop.fs.Path;importorg.apache.hadoop.io.IOUtils;importjava.io.BufferedInputStream;importjava.io.FileInputStream;importjava.io.InputStream;importjava.io.OutputStream;publicclassHDFSExample{publicstaticvoidmain(String[]args)throwsException{Configurationconf=newConfiguration();conf.set("fs.defaultFS","hdfs://localhost:9000");FileSystemfs=FileSystem.get(conf);//其他操作...}}```在这个代码中,FileSystem.get(conf)就是获取客户端对象的部分。我需要使回答完整:-解释步骤。-提供代码。-添加引用。生成相关问题:基于主题,如常见操作、错误处理、优化等。确保中文回答。最终回答结构:1.引言:简要说明获取HDFS客户端对象的重要性。2.步骤:-步骤1:创建Configuration对象并设置HDFS地址。-步骤2:使用FileSystem.get(conf)获取FileSystem对象。-步骤3:使用对象进行文件操作(如上传、下载)。3.完整代码示例。4.引用站内内容。5.相关问题。</think>### 如何使用Java API操作HDFS并获取客户端对象 在Hadoop分布式文件系统(HDFS)中,客户端对象通常指`FileSystem`对象,它是Java API的核心接口,用于执行文件操作(如上传、下载、创建目录等)。获取该对象的步骤如下(基于Hadoop 3.x版本): #### 步骤详解 1. **创建Configuration对象**: 配置HDFS连接参数,包括NameNode地址(例如`hdfs://localhost:9000`)。Configuration对象封装了Hadoop集群的配置信息[^1]。 2. **获取FileSystem客户端对象**: 通过`FileSystem.get(conf)`方法获取客户端实例。此方法基于配置自动连接到HDFS集群,返回一个可操作的FileSystem对象[^2]。 3. **使用客户端对象进行操作**: 调用FileSystem对象的方法执行具体任务,例如: - `mkdirs(Path)` 创建目录 - `copyFromLocalFile()` 上传文件 - `open(Path)` 读取文件 #### 完整示例代码 以下是一个简单的Java程序,展示如何获取FileSystem客户端对象并上传文件到HDFS: ```java import org.apache.hadoop.conf.Configuration; import org.apache.hadoop.fs.FileSystem; import org.apache.hadoop.fs.Path; import org.apache.hadoop.io.IOUtils; import java.io.BufferedInputStream; import java.io.FileInputStream; import java.io.InputStream; import java.io.OutputStream; public class HDFSClientExample { public static void main(String[] args) throws Exception { // 步骤1: 创建Configuration对象并设置HDFS地址 Configuration conf = new Configuration(); conf.set("fs.defaultFS", "hdfs://localhost:9000"); // 替换为你的NameNode地址 // 步骤2: 获取FileSystem客户端对象 FileSystem fs = FileSystem.get(conf); // 这是核心的客户端实例 // 步骤3: 使用客户端对象上传本地文件到HDFS String localFilePath = "./test.txt"; // 本地文件路径 String hdfsFilePath = "/user/hadoop/test.txt"; // HDFS目标路径 try (InputStream in = new BufferedInputStream(new FileInputStream(localFilePath)); OutputStream out = fs.create(new Path(hdfsFilePath))) { IOUtils.copyBytes(in, out, 4096, true); // 执行文件上传 System.out.println("文件上传成功!"); } fs.close(); // 关闭客户端连接 } } ``` #### 关键说明 - **依赖要求**:需添加Hadoop客户端库(如`hadoop-client`)到项目依赖(Maven或Gradle)。 - **配置细节**: - `fs.defaultFS` 必须匹配你的HDFS集群地址(例如`hdfs://namenode:8020`)。 - 如果集群启用Kerberos认证,需额外配置安全参数[^3]。 - **最佳实践**: - 使用`try-with-resources`确保资源关闭,避免连接泄漏。 - 在生产环境中,通过`FileSystem.get(URI, conf)`指定URI增强灵活性。 参考站内内容:在Hadoop环境搭建完成后,我们可以通过Java API来进行HDFS的操作[^3]。使用注解@Test进行测试,调用的还是Linux中的mkdir,让客户端连接对象进行调用(注意这里客户端连接对象要在类的上方使用private进行定义,方便在下方方法中的调用)[^2]。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值