一、HDFS读文件过程
1.1 实例代码:
package com.liangjya.hadoop.demo;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.net.URI;
import java.net.URISyntaxException;
import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.fs.FSDataInputStream;
import org.apache.hadoop.fs.FileSystem;
import org.apache.hadoop.fs.Path;
import org.apache.hadoop.io.IOUtils;
import org.junit.Before;
public class HDFSDemo {
FileSystem fSystem =null;
@Before
public void init() throws IOException, URISyntaxException{
fSystem = FileSystem.get(new URI("hdfs://simulate:9000"), new Configuration());
}
public static void main(String args[]){
try {
FileSystem fSystem = FileSystem.get(new URI("hdfs://simulate:9000"), new Configuration());
FSDataInputStream in=fSystem.open(new Path("/words"));
FileOutputStream out = new FileOutputStream(new File("/usr/cloud/hadoop-words"));
IOUtils.copyBytes(in, out, 2048, true);
} catch (IOException e) {
e.printStackTrace();
} catch (URISyntaxException e) {
e.printStackTrace();
}
}
}
1.2 读取过程图:
1.初始化FileSystem,然后客户端(client)用FileSystem的open()函数打开文件
2.FileSystem用RPC调用元数据节点NameNode,得到文件的数据块信息,对于每一个数据块,元数据节点返回保存数据块的 元数据信息(地址、块数等)。
3.FileSystem返回FSDataInputStream给客户端,用来读取数据,客户端调用stream的read()函数开始读取数据。
4.DFSInputStream连接保存此文件第一个数据块DataNode的最近的数据节点,data从数据节点读到客户端(client)
5.当此数据块读取完毕时,DFSInputStream关闭和此数据节点的连接,然后连接此文件下一个数据块的最近的数据节点。
6.当客户端读取完毕数据的时候,调用FSDataInputStream的close函数。
7.在读取数据的过程中,如果客户端在与数据节点通信出现错误,则尝试连接包含此数据块的下一个数据节点。
8. 失败的数据节点将被记录,以后不再连接。
Hadoop中的网络拓扑 在Hadoop集群中如何衡量两个节点的远近呢?要知道,在高速处理数据时,数据处理速率的唯一限制因素就是数据在不同节点间的传输速度:这是由带宽的可怕匮乏引起的。所以我们把带宽作为衡量两个节点距离大小的标准。但是计算两个节点之间的带宽是比较复杂的,而且它需要在一个静态的集群下才能衡量,但Hadoop集群一般是随着数据处理的规模动态变化的(且两两节点直接相连的连接数是节点数的平方)。于是Hadoop使用了一个简单的方法来衡量距离,它把集群内的网络表示成一个树结构,两个节点之间的距离就是他们离共同祖先节点的距离之和。树一般按数据中心(datacenter),机架(rack),计算节点(datanode)的结构组织。计算节点上的本地运算速度最快,跨数据中心的计算速度最慢(现在跨数据中心的Hadoop集群用的还很少,一般都是在一个数据中心内做运算的)。 假如有个计算节点n1处在数据中心c1的机架r1上,它可以表示为/c1/r1/n1,下面是不同情况下两个节点的距离: • distance(/c1/r1/n1, /c1/r1/n1) = 0 (processes on the same node) • distance(/c1/r1/n1, /c1/r1/n2) = 2 (different nodes on the same rack) • distance(/c1/r1/n1, /c1/r2/n3) = 4 (nodes on different racks in the same data center) • distance(/c1/r1/n1, /c2/r3/n4) = 6 (nodes in different data centers) 如下图所示:
|
二、HDFS写文件过程
package com.liangjya.hadoop.demo;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.URI;
import java.net.URISyntaxException;
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 org.junit.Before;
import org.junit.Test;
public class HDFSDemo {
FileSystem fSystem =null;
@Before
public void init() throws IOException, URISyntaxException{
fSystem = FileSystem.get(new URI("hdfs://simulate:9000"), new Configuration());
}
@Test
public void testUpload(){
try {
InputStream inputStream = new FileInputStream("/usr/cloud/hadoop-words");
OutputStream outputStream = fSystem.create(new Path("/uploda-words"));
IOUtils.copyBytes(inputStream, outputStream, 4096, true);
} catch (Exception e) {
e.printStackTrace();
}
}
}
HDFS写文件过程:
replica是如何分布的 Hadoop在创建新文件时是如何选择block的位置的呢,综合来说,要考虑以下因素:带宽(包括写带宽和读带宽)和数据安全性。如果我们把三个备份全部放在一个datanode上,虽然可以避免了写带宽的消耗,但几乎没有提供数据冗余带来的安全性,因为如果这个datanode当机,那么这个文件的所有数据就全部丢失了。另一个极端情况是,如果把三个冗余备份全部放在不同的机架,甚至数据中心里面,虽然这样数据会安全,但写数据会消耗很多的带宽。Hadoop 0.17.0给我们提供了一个默认replica分配策略(Hadoop 1.X以后允许replica策略是可插拔的,也就是你可以自己制定自己需要的replica分配策略)。replica的默认分配策略是把第一个备份放在与客户端相同的datanode上(如果客户端在集群外运行,就随机选取一个datanode来存放第一个replica),第二个replica放在与第一个replica不同机架的一个随机datanode上,第三个replica放在与第二个replica相同机架的随机datanode上。如果replica数大于三,则随后的replica在集群中随机存放,Hadoop会尽量避免过多的replica存放在同一个机架上。选取replica的放置位置后,管道线的网络拓扑结构如下所示:
|