HDFS读数据流程
1.跟namenode通讯查询元数据,找到文件块所在的datanode服务器
2.挑选一台datanode(就近原则,然后随机)服务器,请求建立socket流
3.datanode开始发送数据(从磁盘里读取数据放入流,以packet为单位做校验)
4.客户端以packet为单位接收,先在本地缓存,然后写入文件
HDFS写数据流程
1.跟namenode通讯请求上传数据,namenode查看目标文件是否已经存在,父目录是否存在
2.namenode返回是否可以上传
3.client请求第一个block该上传到哪些datanode服务器上
4.namenode返回3个datanode服务器ABC
5.client请求3台datanode中的A上传数据(本质是RPC调用,建立pipeline),A收到请求会继续调用B,然后B调用C,将整个pipeline建立完成,逐级返回客户端
6.client开始向A上传第一个block(先从磁盘放到一个本地缓存),以packet(64k)为单位,通过socket流传送,A收到packet就会传给B,B传给C;A每穿一个packet会放入一个应答队列,每个datanode节点接收packet成功后会向它的上一级传送一个标志成功的响应,文件就以packet为单位源源不断的传送玩第一个block,client再向namenode申请开始上传第二个block。
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;
import org.junit.Test;
public class HdfsIO {
FileSystem fs = null;
@Before
public void init() throws IOException, InterruptedException, URISyntaxException{
fs =FileSystem.get(new URI("hdfs://127.0.0.1:9000"), new Configuration(), "hadoop");
}
/**
* 用IO流下载数据
* @throws IllegalArgumentException
* @throws IOException
*/
public void testDownload() throws IllegalArgumentException, IOException{
FSDataInputStream in = fs.open(new Path("/user/hadoop/in/test.log"));
FileOutputStream out = new FileOutputStream("/home/hadoop/chinesecalendar3.log");
IOUtils.copyBytes(in, out, new Configuration());
IOUtils.closeStream(in);
IOUtils.closeStream(out);
}
/**
* 从指定偏移量读取HDFS中的文件数据,具有重大意义
* 在分布式数据处理时,可以将数据分片
* @throws IllegalArgumentException
* @throws IOException
*/
@Test
public void testSeek() throws IllegalArgumentException, IOException{
FSDataInputStream in = fs.open(new Path("/user/hadoop/in/t1.txt"));
in.seek(6);
FileOutputStream out = new FileOutputStream("/home/hadoop/t1.log");
IOUtils.copyBytes(in, out, 4096);
IOUtils.closeStream(in);
IOUtils.closeStream(out);
}
/**
*IO流上传文件
* @throws IllegalArgumentException
* @throws IOException
*/
@Test
public void testUpload() throws IllegalArgumentException, IOException{
FileInputStream in = new FileInputStream("/home/hadoop/t1.log");
FSDataOutputStream out = fs.create(new Path("/user/hadoop/in/t2.txt"));
IOUtils.copyBytes(in, out, 4096);
IOUtils.closeStream(in);
IOUtils.closeStream(out);
}
public static void main(String[] args) {
}
}