Hadoop快速实战(三)——HDFS原理
2017-02-13 17:16
239 查看
一、HDFS架构
主要包括:NameNode
DataNode
SecondaryNameNode
NameNode工作原理
存储流程1、客户端发送存储请求
2、服务端NameNode接收请求后,返回分配的DataNode节点
3、客户端收到信息后,将文件切分为多个block写入到DataNode
4、DataNode将得到的blk同步到其他DataNode形成备份,一般三份
5、如果DataNode备份失败,会将信息返回给NameNode,NameNode将重新分配备份服务器,确保备份三份
每一个block的基本信息(例如:存储路径),以元数据的形式存储在NameNode上。元数据相当于是所有文件的目录,既小又多。如何保证元数据的快速、稳定显得非常重要!
NameNode管理元数据原理
1、客户端发送存储请求
2、NameNode往edits log中记录元数据操作日志
3、NameNode返回分配的DataNode节点
4、客户端向DataNode写文件
5、写完之后,发送信息通知NameNode
6、NameNode将edits log中的元数据更新到内存中。
7、每当editslog写满时,需要将新的元数据刷到fsimage文件中。
*edits log非常小,只有几十兆,每次存满后都会flush到fsimage中永久保存
*fsimage中的元数据和NameNode内存中的元数据是基本保持一致的,如果不一致,查看edits log
edits log如何刷到fsimage中,原理解析:
1、当NameNode发现edits log已经写满,通知SN(SecondaryNameNode),执行checkpoint(合并)操作。
2、SN通知NameNode,停止往edits文件中写数据。新的元数据写到edits.new中。
3、SN下载NameNode中的edits文件和fsimage文件(http get)
4、SN合并edits和fsimage,形成新文件fsimage.checkpoint
5、上传新的fsimage.checkpoint给NameNode
6、fsimage.checkpoint替换原来的fsimage,edits.new替换原来的edits
*checkpoint触发条件,既可以是大小,也可以是时间,默认edits达到64M时执行,默认间隔时间3600秒。
上述的HDFS存储流程,以及元数据的管理机制,可以说是比较稳定的了。但是整个架构NameNode只有一台,一旦宕机,则导致整个服务无法继续对外提供。
DataNode工作原理
DataNode提供真实文件数据的存储服务。基本概念:
block:基本存储单位(文件块)。如果一个文件小于一个block大小,并不占用整个文件块的存储空间。一个block的默认大小是128M,可以通过配置文件修改。
可以动手上传一个文件试试看,如果大于128M,一定会被切分的,切分后的文件可以手动合并回来
$ cat blk2 >blk1
二、linux下安装eclipse并配置环境
导入hdfs的jar包,导入依赖,导入common的jar包,导入common的依赖三、HDFS操作实例
写一个HdfsUtil的Class文件,编写一个下载的方法fs就是HDFS的客户端
// org.apache.hadoop.configuration // 用来读配置文件的,把key-value读到对象中方便获取 // 也可以直接设置参数conf.set(name,value); Configuration conf = new Configuration(); // core-site.xml中配置过 conf.set("fs.defaultFS","hdfs://服务明名称:9000/") // fs就是hdfs的客户端 FileSystem fs = FileSystem.get(conf); Path src = new Path("hdfs://服务名称:9000/文件名称") FSDataInputStream in = fs.open(src); FileOutputStream os = new fileOutputStream("/本地目 4000 录/文件命名") IOUtils.copy(in,os);
如果不在conf中设置fs.defaultFS,则拷贝core-site.xml到项目根目录下
在windows项目下用户不是linux下的用户,设置VM arguments
-DHADOOP_USER_NAME=hadoop
其中hadoop是用户名,我的是fangxin
可以通过交互界面查看hadoop文件内容
之前的实现太繁琐
上传直接使用fs.copyFromLocalFile(src,dst)实现
而身份认证直接使用
// 模拟用户,除了上述的配置方式,也可以通过代码解决 FileSystem.get(new URI("hdfs://默认地址"),conf,"身份")
代码如下:
before
FileSystem fs = null; @Before public void init() throws IOException, URISyntaxException, InterruptedException { Configuration conf = new Configuration(); conf.set("fs.defaultFS","hdfs://192.168.49.31:9000/"); // 根据配置信息,去获取一个具体文件系统的客户端操作实例对象 fs = FileSystem.get(new URI("hdfs://192.168.49.31:9000/"),conf,"fangxin"); }
这样就以hadoop的身份访问了。
上传
@Test public void uploda() throws IOException { fs.copyFromLocalFile(new Path("F:\\BaiduYunDownload\\aa.txt"),new Path("hdfs://192.168.49.31:9000/")); }
下载
@Test public void download() throws IOException { fs.copyToLocalFile(new Path("/aa.txt"),new Path("f:/BaiduYunDownload/")); }
创建文件夹
@Test public void mkdir() throws IOException { fs.mkdirs(new Path("/aaa/bbb/ccc")); }
删除文件夹或文件
@Test public void rmdir() throws IOException { fs.delete(new Path("/aaa"),true); }
迭代遍历文件
@Test public void listFiles() throws IOException { RemoteIterator<LocatedFileStatus> files = fs.listFiles(new Path("/"), true); while(files.hasNext()){ LocatedFileStatus file = files.next(); Path filePath = file.getPath(); String fileName = filePath.getName(); System.out.println(fileName); } }
遍历当前目录下所有内容,不迭代
@Test public void listStatus() throws IOException { FileStatus[] listStatus = fs.listStatus(new Path("/")); for(FileStatus status: listStatus){ String name = status.getPath().getName(); System.out.println(name); } }
总结:listFiles列出的是文件信息,而且提供递归遍历
listStatus 可以列出文件和文件夹信息,但是不提供自带的递归遍历
FileSystem设计原理
FileSystem抽象类解耦了具体文件系统的实现四、RPC远程过程调用
简单说:两个进程间的调用。传统的controller和service是在一套程序中的,或者说一个项目中的,这样我们直接用service的实例完成我们的业务。但是考虑到如果controller和service分离到两台服务器上,怎么办呢?这时候我们是不可能直接在controller层创建service的实例的。
这时候我们只能通过网络通信。网络通信需要相关的网络编程的知识。
socket就是一种网络通信协议。
controller调用socket client,
socket client和socket server通信,
socket server反射实例,调用目标方法,获取结果
序列化结果,服务端再将结果通过socket传递给客户端
客户端的socket将结果返回给controller
这就是网络通信的基本思路。协议是tcp。
不同的框架对网络通信的处理不同,协议不同。但是其实都是网络通信的一种
webservice的协议是soap
jdk中的RMI
hadoop中的叫RPC。节点间的通信基本都使用RPC
hadoop中的rpc的调用非常的好,给人一种感觉就像在本地一样。
1、代理对象proxy和socket实现相同的接口
2、调用proxy的方法,例如登录。实际是走的socket通信的方法
3、服务端socket获取到信息,调用服务端目标方法
4、结果返回给客户端。
通过一个中间接口,加代理方式,实现类似于本地要用的风格。
RPC实例
hadoop的RPC框架存在于common包中,你可以不用hadoop但使用RPC测试文件准备
一个实现,一个接口,一个启动,共三个文件。服务应该部署在服务端,我这里写在了linux虚拟服务器上。
接口
package com.rpc; /** * @author fangxin * @description ${END} * @date 2017/2/13 0013. */ public interface LoginService{ // 如果没有版本号,运行报错 static final long versionID = 1L; String login(String username); }
如果不写版本号,会报如下错误
实现
package com.rpc; /** * @author fangxin * @description ${END} * @date 2017/2/13 0013. */ public class LoginServiceImpl implements LoginService{ @Override public String login(String username) { return "welcome "+username; } }
启动类
package com.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; /** * @author fangxin * @description ${END} * @date 2017/2/13 0013. */ public class Starter { public static void main(String[] args) throws HadoopIllegalArgumentException, IOException { RPC.Builder builder = new RPC.Builder(new Configuration()); builder.setBindAddress("192.168.49.31").setPort(10000).setProtocol(LoginService.class).setInstance(new LoginServiceImpl()); Server server = builder.build(); server.start(); } }
准备好后,运行Starter中的main方法,login方法就支持调用了。
服务端准备好后,开始准备客户端
package com.rpc; import org.apache.hadoop.conf.Configuration; import org.apache.hadoop.ipc.RPC; import java.io.IOException; import java.net.InetSocketAddress; /** * @author fangxin * @description ${END} * @date 2017/2/13 0013. */ public class LoginController { public static void main(String[] args) throws IOException { LoginService proxy = RPC.getProxy(LoginService.class,1L,new InetSocketAddress("192.168.49.31",10000),new Configuration()); String result = proxy.login("angelababy"); System.out.println(result); } }
除了LoginController.java,客户端还要准备一个接口文件,这个文件应该和服务端完全一致,目录都要一样
RPC优点
有一些服务是长期对外提供服务的,传统的项目,一旦service改变,引用他的jar包的所有服务都要更新才行。而如果采用RPC则不需要了。另外,可以将service单独抽离出来,这样如果service承载能力不够了,可以有针对性的扩大承载能力。
相关文章推荐
- Hadoop实战-中高级部分 之 HDFS原理 架构和副本机制
- 王家林 云计算分布式大数据Hadoop实战高手之路第七讲Hadoop图文训练课程:通过HDFS的心跳来测试replication具体的工作机制和流程
- hadoop基础学习-hdfs原理
- Hadoop实战-初级部分 之 HDFS API
- hadoop HDFS原理基础知识
- HDFS append原理与代码分析(Hadoop 2.0)
- 用hadoop中的libhdfs和fuse-dfs构建快速云存储
- Hadoop实战-中高级一部分 之 Hadoop作业调优参数调整及原理
- 王家林的“云计算分布式大数据Hadoop实战高手之路---从零开始”的第十一讲Hadoop图文训练课程:MapReduce的原理机制和流程图剖析
- 【Hadoop】HDFS的运行原理
- Hadoop2.2.0中HDFS的高可用性实现原理
- Hadoop HDFS——Hadoop实战初级部分学习笔记
- [置顶] Hadoop2.2.0中HDFS的高可用性实现原理
- [置顶] Hadoop2.2.0中HDFS的高可用性实现原理
- Hadoop实战-初级部分 之 HDFS
- Hadoop实战-初级部分 之 HDFS API
- hadoop学习笔记-HDFS原理
- 【Hadoop】HDFS的运行原理
- hadoop2.2.0 分布式存储hdfs完全分布式搭建及功能测试记录(一)----架构及原理介绍