Hadoop入门-2

1.分布式文件系统与HDFS

2.HDFS体系结构与基本操作

3.HDFS的shell操作

4.JAVA接口及常用API

首先了解一下存放数据的过程:Clinet请求上传数据,和NameNode建立通信(RPC),NameNode查询元数据信息,将信息反馈给客户端,此时客户端再将数据传送给DataNode中去。为了数据的安全,HDFS的操作是将DataNode进行了一波复制,水平的进行传递,直到符本的数量和NameNode的数量一致就OK了。以流水线的方式来进行书写,效率更高。副本是DataNode和DataNode进行通信及管理。            

数据的分块:200M的文件会被分块,默认大小块:128M,Hadoop大小是64M。写满一个块申请一个块。好处:通过偏移量,如果某一块Down掉了,可以从当前块继续读。paperline:流水线。

分布式文件系统:

        数据量越来越多,允许文件通过网络在多台主机上分享的文件系统,让多台机器上的多用户分享文件和存储空间。优点:通透性,容错,管理系统很多。分了8块同时写是不允许的。小文件不适合。

常见的分布式文件系统:GFS,HDFS,LUSTRE,GRIDFS,CEPH,TFS(淘宝)。

HDFS的Shell:通过命令行的方式来操作HDFS。

查看HDFS上的文件内容情况:

[root@itcast01 sbin]# hadoop fs -ls hdfs://itcast01:9000/

可以进行简写:查看HDFS的根

[root@itcast01 sbin]# hadoop fs -ls /

从本地拷贝:类似于上传:[root@itcast01 /]# hadoop fs -copyFromLocal /locale.conf /in.log

查看内容:[root@itcast01 /]# hadoop fs -cat /in.log    分页看:

[root@itcast01 /]# hadoop fs -cat /in.log | more  利用管道符,输出作为输入

copyToLocal:拷贝到本地:类似下载

[root@itcast01 /]# hadoop fs -count /    :/文件夹/文件/大小

[root@itcast01 /]# hadoop fs -rm -r /tmp/        删除文件

cp:两个HDFS的路径,从哪里拷贝到哪里。

ls -r递归查看,可以看到目录下的文件  -h:加单位,为m,可读

moveFromLocal/MoveToLocal/mv          移动后删除。

-put上传   rm -r      tail查看文件尾部内容  text:查看内容

touchz:创建一个空文件

[root@itcast01 /]# hadoop fs -chmod a+x /in.log    添加执行权限

[root@itcast01 /]# hadoop fs -chmod -R -x /wcout  减少执行权限

[root@itcast01 /]# hadoop fs -chown supergroup /in.log    修改所有者更改为super组 ----->

[root@itcast01 /]# hadoop fs -chown supergroup:root /wcout

更改所属用户和所属组。递归-R

利用新的方式:hdfs dfs -ls -R /       :新的接口  2.0


HDFS架构

NameNode                    DataNode            Secondary NameNode

NamNode:负责管理  DataNode:负责存储数据  Secondary NameNode:进行协助,而不是热备。

元数据存储细节:内存一份/磁盘一份

NameNode(FileName,replicas,block0ids,id2host...)

/test/a.log,3,{blk_1,blk_2},[{blk_1:[h0,h1,h3]}],[{blk_2:[h0,h2,h4]}],

文件名  副本数  分为几块    每一块所在的位置,第一块的副本存放在:h0,h1,h3机器上。第二块副本存放的位置在:h0,h2,h4上。

文件是否被损坏:校验盒机制:CRC32机制。矫正是否被损坏。

元数据:仓库管理的账本。100斤白菜,存放位置等内容,类似与WMS的出库单入库单,记录的描述信息。

NameNode:是整个文件系统的管理节点。它维护着整个系统的文件目录树。NameNode进行记录这些映射关系,文件放在哪个目录下,文件目录的元数据信息和每个文件对应的数据块列表。存放了多少块,哪个机器上,多少个副本等。接受用户的请求。

fsimage:元数据镜像文件,存储某一时段NameNode内存元数据信息。不是实时同步(伪分布式),放在磁盘上。如果是真实状况的话则会实时同步:Hadoop2。meteData:元数据,放在内存中。

edits:操作日志文件 

fstime:保存最近一次checkpoint的时间

以上这些文件是保存在linux的文件系统中。在tmp中,都是十分重要的内容。

NameNode的工作特点:始终在内存中保存metedata,用于处理"读请求"

有“写请求时”,namenode首先会写editlog到磁盘,即向edits文件中写日志,成功返回后才会修改内存,并且向客户端返回。

Datanode:

        提供真实文件数据的存储服务。

        文件块:最基本的存储单位。从文件的0偏移开始,默认是64M,Hadoop是128M。最终保存在linux的磁盘之上。块位于tmp/dfs/data/current/BP../current/finalized 里面存放着数据的 块,每一块都有.meta进行描述的块。第二块占的是真实的大小,并非块全部的大小。Replication。多副本,默认是3个。心跳机制,小弟主动将信息汇报给老大,如果没法送心跳机制则说明已经Down了,就让其他的机器再复制一份数据。

使用JAVA接口进行HDFS操作:

        导包,使用工具类。下载代码:

public class HDFSDemo {
public static void main(String[] args) throws IOException, URISyntaxException {
FileSystem fs=FileSystem.get(new URI("hdfs://itcast01:9000"), new Configuration());
        InputStream  in=fs.open(new Path("/words"));
        OutputStream out=new FileOutputStream("d://jkt1.7");
        IOUtils.copyBytes(in, out, 4096,true); //默认的Buffer是4096
}
}

下载没问题,上传的话权限不够,但是可以伪装一个参数来进行上传,伪装root用户。

public class HDFSDemo {
FileSystem fs=null;
@Before
public void init() throws Exception

{

//这里伪装成了root用户来进行写内容,但是对于HDFS还是不够安全

fs=FileSystem.get(new URI("hdfs://itcast01:9000"), new Configuration(),"root");
}

@Test
public void testUpload() throws Exception
{

//读取本地文件系统的文件

InputStream in=new FileInputStream("c://APlayer.dll");

//在HDFS上创建一个文件,返回输出流

OutputStream out=fs.create(new Path("/test.dll"));

//输入->输出

IOUtils.copyBytes(in, out, 4096,true);
}



public static void main(String[] args) throws IOException, URISyntaxException {
FileSystem fs=FileSystem.get(new URI("hdfs://itcast01:9000"), new Configuration());
    InputStream  in=fs.open(new Path("/words"));
    OutputStream out=new FileOutputStream("d://jkt1.7");
    IOUtils.copyBytes(in, out, 4096,true); //默认的Buffer是4096
}


}

//删除文件:注意:这种方法只能删除空文件夹,如果有子文件的话必须要把参数改为true,这里的true和false主要针对是否递归删除。

@Test
public void testDel() throws IllegalArgumentException, IOException{
boolean flag=fs.delete(new Path("/test.dll"),false);
System.out.println(flag);

}

//创建文件夹

@Test
public void testmkdir() throws IllegalArgumentException, IOException{
    boolean b = fs.mkdirs(new Path("/itcast01106"));
    System.out.println(b);
}


RPC:

        远程过程调用协议。例如WebService。不同进程之间的方法调用。http+xml:WebService。跨语言,平台系统间调用的解决方案。例如OA项目(JAVA)想要CRM项目(.NET)的一些数据内容。暴露了一个地址,xml文件,根据xml文件生成一些类。可以调CRM里面的一些方法。OA的类是CRM的接口(代理对象),也就是同一个接口。

动态代理:客户端和服务端同时实现一个接口。

RPC:不同进程之间的方法调用。

Server:

package cn.itcast.hadoop.rpc;

import java.io.IOException;

import org.apache.hadoop.HadoopIllegalArgumentException;
import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.ipc.RPC;
import org.apache.hadoop.ipc.RPC.Server;


public class RPCServer implements Bizable{
public String sayHi(String name){
return  "HI~"+name;
}
public static void main(String[] args) throws Exception{
Configuration conf=new Configuration();
Server server = new RPC.Builder(conf).setProtocol(Bizable.class).setInstance(new RPCServer()).setBindAddress("192.168.8.100").setPort(9527).build();
server.start();
}
}

//接口

package cn.itcast.hadoop.rpc;
public interface Bizable {
public static final long versionID=100000;
public String sayHi(String name);
}

//客户端

package cn.itcast.hadoop.rpc;
import java.io.IOException;
import java.net.InetSocketAddress;
import org.apache.hadoop.conf.Configuration;

import org.apache.hadoop.ipc.RPC;


public class RPCClient {
public static void main(String[] args) throws Exception {
// TODO Auto-generated method stub
//获取到代理对象,是接口的实现类
Bizable proxy = RPC.getProxy(Bizable.class, 10010, new InetSocketAddress("192.168.8.100",9527), new Configuration());
String result = proxy.sayHi("tomcat");
System.out.println(result);
RPC.stopProxy(proxy);
}
}

源码分析:

NameNode/DataNode/SecondaryNameNode都是一个类。

FileSystem下的子类:DistributeFileSystem。

F5:进入方法。 

F6:不进入方法。

F7:跳出该方法。        远程DeBug

FileSystem fs=FileSystem.get(new URI("hdfs://itcast01:9000"), new Configuration());  //找到实现类DistributeFileSystem

首先load URI这个类,然后Configuration这个类,再跳转到get这个方法里面。DistributeFileSystem单例。懒汉模式,线程不安全的。等到需要用的时候再new一个对象出来。  一般看方法,看返回值,发返回值的类型。然后该返回值在哪里进行创建的。

1.通过读取配置信息获取一个实现类   2.通过反射得到一个对象  3.调用initsalize方法来new了一个DFSClient。new DFSClient()->构造方法。

对象初始化过程:类加载器->private static int a=1  ->静态代码块。

配置文件-实现类-反射初始化->调用init方法->new DFSClient(成员变量)->Server端代理对象->增强->DFS的成员变量。

new Path()->fs.Open方法。抽象类->子类。匿名回调函数doCall。类->子类。new 接口():实现方法。  dfs.open方法。








你可能感兴趣的:(hadoop)