I know, i know 地球另一端有你陪我
一、关于 Hadoop 的 hdfs
1、hdfs 中的节点
从节点(data node)负责存储数据: 数据节点具有储存数据、读写数据的功能, 其中存储的数据块(block)比较类似于硬盘中的"扇区"概念,是 HDFS 存储的基本单位
主节点(name node)负责指挥其它节点: 任何一个"文件系统"(File System, FS) 都需要具备根据文件路径映射到文件的功能, 命名节点就是用于储存这些映射信息并提供映射服务的计算机, edits 文件用来记录记录每次对 hdfs 的操作,fsimage 文件存储文件路径的映射, 在整个 HDFS 系统中扮演"管理员"的角色,因此一个 HDFS 集群中只有一个命名节点
次主节点(Secondary NameNode)负责协助主节点: 默认每过一个小时,或当前 edits 大小超出 64MB, 次主节点就会整合上一次的 fsimage 和这个小时里的 edits,生成新的 fsimage 这个过程成为 checkpoiint
HDFS 命名空间(NameSpace): HDFS 支持传统的层次型文件组织结构。 用户或者应用程序可以创建、删除、移动或重命名文件,将文件保存在这些目录里 这种结构称为命名空间
在主节点上,为了加快用户访问的速度,会把整个命名空间信息都放在内存中, 当存储的文件越多时,那么主节点就需要越多的内存空间
2、分布式存储
hadoop 将从节点划分为众多同样大小的块(block),每个块分配了 128MB 的空间大小
1、文件被上传后,会被自动划分,当小于 128MB,会被直接存储到该 block
2、当文件超出 128MB,系统允许10%的溢出,即小于 140.8MB ,一样会被存于一个 block
3、当文件超出允许溢出的范围,文件将会被储存于不同的 block 当中,即分布式存储
因此在分布式存储系统中,一个文件的数据可能分散在不同节点中
4、java 连接 hdfs
Configuration con = new Configuration();
con.set("dfs.replication","1");
URI uri = new URI("hdfs://master:9000");
FileSystem fs = FileSystem.get(uri, con);
fs.mkdirs(new Path("/mk"));
fs.delete(new Path("/mk"),true);
FileStatus[] fileStatuses = fs.listStatus(new Path("/"));
FileStatus fileStatus = fs.getFileStatus(new Path("/mk.txt"));
FSDataOutputStream creat = fs.create(new Path("/test.txt"));
BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(creat));
bw.write("helloworld");
bw.close();
creat.close();
FSDataInputStream open = fs.open(new Path("/test.txt"));
BufferedReader br = new BufferedReader(new InputStreamReader(open));
String string;
while((string=br.readLine())!=null){
System.out.println(string);
}
br.close();
open.close();
Path local1 = new Path("D:\\date\\test1.txt");
Path hdfs1 = new Path("/");
fs.copyFromLocalFile(local1,hdfs1);
Path local2 = new Path("D:\\soft\\");
Path hdfs2 = new Path("/test.txt");
fs.copyToLocalFile(false,hdfs2,local2);
5、hdfs 读取流程
1.连接 HDFS,调用 FileSystem 对象的 open 方法,其实是一个 DistributedFileSystem 的实例
2.DistributedFileSystem 通过 rpc 在 name node 中获得文件的第一个 block 的路径映射(location),同一 block 按照副本数会返回多个 location, ???这些映射按照 hadoop 拓扑结构排序,距离客户端近的排在前面
3.前两步会返回一个 FSDataInputStream 对象,该对象会被封装成 DFSInputStream 对象, ???当客户端调用 read 方法,DFSInputStream 最会找出离客户端最近的datanode 连接
4.数据从 datanode 通过流进行输入
5.当第一块的数据读完,就会关闭指向第一块的 data node 连接,接着读取下一块 ???如果所有的块都读完,这时就会关闭掉所有的流 关于异常 如果在读数据的时候,DFSInputStream 和 datanode 的通讯发生异常, 就会尝试正在读的 block 的排第二近的 datanode,并且会记录哪个datanode发生错误, 剩余的 blocks 读的时候就会直接跳过该datanode
DFSInputStream 也会检查 block 数据校验和,如果发现一个坏的 block, 会先报告到 namenode 节点,然后在其他的 datanode 上读该 block 的副本
读取的就近原则就是为客户端直接连接提供最优的 datanode 连接, hdfs通过datanode集群可以承受大量客户端的并发访问
6、hdfs 写入流程
1.客户端通过调用 DistributedFileSystem 的 create 方法写入
2.DistributedFileSystem 通过RPC调用 namenode 去创建一个没有 blocks 关联的新文件, ???创建前,namenode 会做各种校验,比如文件是否存在,客户端有无权限去创建等。 ???如果校验通过,namenode就会记录下新文件,否则就会抛出IO异常
3.前两步结束后会返回 FSDataOutputStream 的对象,同写入相似 ???FSDataOutputStream 被封装成 DFSOutputStream ???DFSOutputStream 会把数据切成一个个小 packet,然后排成队列 data quene
4.namenode 会计算出这个新的 packet 最适合存储的在哪几个 datanode 里, ???比如副本数是3,那么就找到3个最适合的 data node,把他们排成一个 pipeline, ???将 packet 向对应的 data node 依次进行输出
5.过程中会生成另一个队列 ack queue,内容同 data quene 完全相同,负责验证, ???当一个 packet 输出完毕,会等待 datanode 的收到响应, ???若对应的所有 datanode 都表示已经收到,这时 akc queue 会把对应的 packet 移除
6.客户端完成写数据后调用 close 方法关闭写入流
7.通知 name node 整合文件的路径映射 关于异常 如果在写的过程中某个 datanode 发生错误,会采取以下几步: 1)pipeline 被关闭掉; 2)为了防止丢包 ack queue 里的 packet 会同步到 data queue 里; 3)把产生错误的 datanode 上当前在写但未完成的 block 删掉;(原子性) 4)block 剩下的部分被写到其余正常的 data node 中;(副本) 5)name node 找到另外的 data node 去创建这个块的复制(整合副本信息)
总结
hadoop dfsadmin -safemode get 命令是用来查看当前 hadoop 安全模式的开关状态
hadoop dfsadmin -safemode enter 命令是打开安全模式
hadoop dfsadmin -safemode leave 命令是离开安全模式
单纯修改从节点数据存储位置中的数据,是无法影响到主节点中获得的数据的 主节点存储的信息会详细到行!?
|