绪论
本周主要学习了分布式存储的相关知识点,并且以小组为单位做了一个仿百度云项目(BS)。
1、HADOOP的历史
Google在2002-2004年间以三大论文的发布向世界推送了其云计算的核心组成部分GFS、MapReduce以及BigTable。
Doug Cutting使用Java语言对Google的云计算核心技术(主要是GFS和MapReduce)做了开源的实现。后来,Apache基金会整合Doug Cutting以及其他IT公司(如Facebook等)的贡献成果,开发并推出了Hadoop生态系统。Hadoop是一个搭建在廉价PC上的分布式集群系统架构,它具有高可用性、高容错性和高可扩展性等优点。
hadoop生态圈的核心组件有HDFS、MapReduce、yarn、common。广义上说泛指大数据技术相关的开源组件或产品,如hdfs、yarn、hbase、hive、spark、pig、zookeeper、kafka、flume、phoenix、sqoop。
2、HDFS存储原理
2.1、各个角色的作用
2.1.1、NameNode
接收客户端的读写请求、管理元数据、管理DataNode。
(元数据包括上传文件的权限、属主及属组、上传文件的时间、上传文件的block数及id号、每一个block块的位置信息(DataNode集群启动时汇报、不会持久化)、各个DataNode的位置信息)
2.1.2、DataNode
接收客户端的读请求、存储block块、向active状态的NameNode汇报心跳、构建pipeline管道、管理本机上的block块元数据。
2.1.3、SecondaryNameNode
主要作用是负责持久化,即拉取(文件拉取之时,在NN节点上回创建edits_new ,目的就是为了存储在合并期间对HDFS的操作)NameNode节点上的edits和fsimage文件(edits文件存储客户端对HDFS的操作;fsimage存储元数据),对其进行合并,合并过程如下:
1、基于拉来的edits文件重演 产出元数据
2、将重演产出的元数据合并到fsimage中
3、将合并后fsimage推送给NN
4、将edits.new文件的后缀去掉
合并触发机制:超过3600s就合并或者edits文件大小超过64M。
2.1.4、ZKFC
作用:
1、监控各自的NameNode,将监控的情况汇报给ZK集群。
2、接受zk的选举结果,确认一下另外一个NameNode是否真的挂了,将自己监控的NN提升为active状态
2.1.5、JournalNode
写数据的时候只需要保证半数以上的节点写入成功就可以了。(防止出现脑裂问题、网络分区问题)
最终一致性/弱一致性
存储的是edits文件
2.1.6、Standby状态的NameNode(备用NameNode)
监控journalNode中数据变化,实时更新自己的内存元数据
将内存中元数据持久化到fsimage中,然后推送给NN
2.2、HDFS的读写流程
2.2.1、读流程
客户端发起向nameNode发起读请求,NameNode查找到该请求的资源在哪个DaataNode上,将该DataNode的位置信息返回给客户端客户端根据这个位置信息去找到该DataNode并且发出读请求。最后DataNode将数据返回给客户端。
2.2.2、写流程
首先客户端携带着文件名、文件大小、文件所有者等信息请求NameNode,NameNode计算出需要多少个block块(128M),及每个block块需要存放在哪个DataNode上(负载不高的DataNode)。NameNode将这些信息返回给客户端。由于备份机制,所以一个block默认需要传到三台DataNode上。这三台DataNode与客户端之间将形成一个pipeline管道。客户端将需要传递的block块切割成一个个的小的packet(64k),将packet在管道里源源不断的传输。DataNode将block传输完毕后,会向NameNode汇报当前的存储情况。
2.3、备份机制
如果是集群外操作(提倡):dataNode与客户端存储在不同的节点上。
如果是集群内提交(不提倡,有网络io问题):dataNode节点将同时作为客户端进行提交
备份过程:
1、第一个block(默认128M,可在dfs.blocksize中修改)存储在一个负载不是很高的服务器上。传输过程将会在客户端与选中的三个节点上构建一个pipeline管道,并且将文件按照字节切割成一个个的packet(64k)在管道中并行传输,如果存储的是中文,会出现乱码问题。
2、第二个block,即第一个备份存储在与第一个block不同机架的随机的一个服务器上。
3、第三个block,即第二个备份存储在与第一个备份相同机架的随机服务器上。
4、其他备份可以随机
小知识点
:集群的dataNode节点数要大于等于副本数+1。
构建pipeline管道和分解成packet的作用:并行传输
2.4、搭建集群的三种模式
1、伪分布式
在一台节点上通过启动不同的进程来表示不同的角色,没有在多个节点进行真的分布式计算,所以叫做伪分布式。
伪分布式一般是作为测试环境使用。
2、完全分布式
在多台服务器上,每台服务器启动不同角色的进程,使用多台服务器组成HDFS集群。搭建完全分布式环境主要需要修改三个文件:hdfs-site.xml、core-site.xml和slaves(配置从节点)。完全分布式的详细搭建过程可以借鉴我的上一篇博客:完全分布式搭建过程
3、高可用的完全分布式
高可用的完全分布式也是不同的角色运行在多台不同的节点上,并且同样是修改hdfs-site.xml、core-site.xml和slaves三个文件。只不过高可用的完全分布式启动过程稍微有点不一样。这里稍微总结一下启动过程:(安装搭建过程请参考:高可用的完全分布式搭建过程)
启动过程:(详细命令见高可用的完全分布式搭建过程的第9-12条)
1、启动zookeeper
2、启动所有的journalnode
3、格式化NameNode
4、将本机的NameNode启动
5、去备用的NameNode节点,同步元数据
6、格式化zfkc
7、关闭所有节点
8、启动hdfs
2.5、HDFS的优缺点
2.5.1、HDFS的优点
1、副本机制,所以数据更安全
2、因为是分布式存储,所以适合批处理
3、高可用行
4、元数据持久化
5、禁掉了一些功能,使得集群更加完美(修改文件功能、文件一旦上传成功,就不能修改block块的大小 )
2.5.2、HDFS的缺点
1、无法毫秒级的读写数据(读写需要找NN请求、写入需要切割文件、形成管道)
2、不适合存储大量的小文件(容易造成元数据过多,NN内存溢出)
3、不能并发写入,但是可以并发的读
小知识点
:如何存储大量的小文件?把小文件合并成大文件,或者联邦机制
2.6、pipeline管道的传输过程
1、客户端向客户端的缓冲区写数据。
2、当缓冲区的数据将达到一个packet(64k)容量大小时。客户端会构建这个数据包,并且把这个数据包输送到pipeline管道里。在传输过程中,客户端不需要管前一个packet是否传输成功,直接可以把下一个构建成功的数据包传送到管道里。
3、当客户端接收到所有packet的反馈信息后,将发送一个关闭请求把pipeline管道关闭。
3、JAVA Api
3.1、准备环境
需要在eclipse配置环境(参考使用eclipse视图操作HDFS的操作流程)。
3.2、操作
先创建配置对象及hdfs对象:
Configuration conf = new Configuration(true);
FileSystem fs = FileSystem.get(conf);
然后直接通过hdfs对象就可以了对hdfs进行操作了:
//取路径下所有文件的信息
listStatus = fs.listStatus(destPath);
//创建新文件
fs.createNewFile(dirPath);
//创建目录
fs.mkdirs(dirPath);
//上传到HDFS
fs.copyFromLocalFile(srcPath_Hdfs, destPath_Hdfs);
//下载
fs.copyToLocalFile(srcPath_Hdfs, destPath_Hdfs);
//删除文件
fs.delete(new Path(path));
//内部拷贝
FileUtil.copy(srcPath.getFileSystem(conf), srcPath, destPath.getFileSystem(conf), destPath,false, conf);
//内部移动
FileUtil.copy(srcPath.getFileSystem(conf), srcPath, destPath.getFileSystem(conf), destPath,true, conf);
//追加
FSDataOutputStream append = fs.append(new Path(path));
4、项目遇到的问题
1、需要在windows下配置HADOOP_USER_NAME这个环境变量,将这个变量值设置为root。不配置这个参数会导致在Windows下无权限在hdfs中对文件进行写入。
2、NameNode格式化成功后,再次启动hdfs集群时,不要重复初始化,初始化会生成一个新的id号,与别的节点id号不一样,无法进行通信。所以再次启动时,只需要按顺序运行启动命令,不要运行格式化命令。
3、配置hosts参数时不要在前两行后面加主机名,会导致hdfs集群启动失败。