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");//读取本地文件系统的文件
InputStream in=new FileInputStream("c://APlayer.dll");
//在HDFS上创建一个文件,返回输出流
OutputStream out=fs.create(new Path("/test.dll"));
//输入->输出
IOUtils.copyBytes(in, out, 4096,true);//删除文件:注意:这种方法只能删除空文件夹,如果有子文件的话必须要把参数改为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;
源码分析:
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方法。