题记:正值学校运动会假期,想吸收点新鲜的血液。心血来潮搭了个hadoop的伪分布式,了解了下HDFS。
HDFS简介
HDFS是Hadoop Distributed File System的简称,即hadoop分布式文件系统。它是Hadoop的核心组件,在最底层保存数据,为hadoop其他组件提供海量数据的数据的存储和读写服务。而Hadoop的另一个核心即MapReduce则是基于HDFS对数据进行调度和分布式计算,这种计算可以理解为常用的读取,删除等处理的操作。原理是由MapReduce的JobTracker节点将计算任务(Job)分成几个Task,每个task为一个子任务,从而对HDFS的分布式数据进行操作。HDFS的特点就是适合存储超大的数据,适式数据的访问,一次写入,多次读写。但是HDFS也有短板:访问的数据没有实时性,由于其对大数据的吞吐量做了优化,所以不适合对数据的实时性访问的场景,并且HDFS不支持并发写,即对文件分片后只能一个块一个块的写。而且Hadoop的权限管理也是一个问题,但是听说可以结合kerberos解决。在hadoop1.0里面对文件也不能追加写…2.0里面可以。。。
hadoop1.0和2.0的HDFS组件有些变化,需要注意的就是块的大小由64MB变为128MB,并且在HDFS的2.0集群中,没有secondaryNameNode。因为NameNode中的镜像文件和内存中的原数据是实时同步的。所以不需要secondaryNameNode来对NameNode的FSImage和Edits文件进行切换,下载,合并,推送过程。这个之后再提。
我下载的是hadoop的1.2.1版本,目前就安装它吧!
hadoop 1.0伪分布式搭建
hadoop安装步骤:
- 安装JDK:apt-get install openjdk-7-jdk;
- 设置环境变量:JAVA_HOME、JRE_HOME、CLASSPATH、PATH
- 下载hadoop安装包并解压到指定目录下;
- 设置环境变量:HADOOP_HOME、PATH
- 修改相关配置文件$HADOOP_HOME/conf:
- 修改hadoop-env.sh,设置JAVA_HOME;
- 修改core-site.xml,设置hadoop.tmp.dir、dfs.name.dir、fs.default.name;
- 修改mapred-site.xml,设置mapred.job.tracker;
- 修改hdfs-site.xml,设置dfs.data.dir;
- 格式化:hadoop namenode -format;
- 启动:start-all.sh
- 检查:jps
完成的环境:
zhxfei@zhxfei-vm:~$ uname -a
Linux zhxfei-vm 4.2.0-27-generic #32~14.04.1-Ubuntu SMP Fri Jan 22 15:32:26 UTC 2016 x86_64 x86_64 x86_64 GNU/Linux
环境变量配置文件:
zhxfei@zhxfei-vm:~$ vim /etc/profile
# /etc/profile: system-wide .profile file for the Bourne shell (sh(1))
# and Bourne compatible shells (bash(1), ksh(1), ash(1), ...).
export JAVA_HOME=/usr/lib/jvm/java-7-openjdk-amd64
export JRE_HOME=$JAVA_HOME/jre
export HADOOP_HOME=/opt/hadoop-1.2.1/
export CLASSPATH=$JAVA_HOME/lib:$JRE_HOME/lib:$CLASSPATH
export PATH=$JAVA_HOME/bin:$JRE_HOME/bin:$HADOOP_HOME/bin:$PATH
export HADOOP_HOME_WARN_SUPPRESS=1 #在执行启动脚本时会有个WRNING ,说Hadoop什么被抑制,添加此条就行
Hadoop的配置文件:
root@zhxfei-vm:/opt/hadoop-1.2.1/conf# vim core-site.xml
<?xml version="1.0"?>
<?xml-stylesheet type="text/xsl" href="configuration.xsl"?>
<!-- Put site-specific property overrides in this file. -->
<configuration>
<property>
<name>hadoop.tmp.dir</name>
<value>/hadoop</value>
</property>
<property>
<name>dfs.name.dir</name>
<value>/hadoop/name</value>
</property>
<property>
<name>fs.default.name</name>
<value>hdfs://zhxfei-vm:9000</value>
</property>
</configuration>
HDFS的配置文件
root@zhxfei-vm:/opt/hadoop-1.2.1/conf# vim hdfs-site.xml
<?xml version="1.0"?>
<?xml-stylesheet type="text/xsl" href="configuration.xsl"?>
<!-- Put site-specific property overrides in this file. -->
<configuration>
<property>
<name>dfs.data.dir</name>
<value>/hadoop/data</value>
</property>
</configuration>
MR的配置文件
root@zhxfei-vm:/opt/hadoop-1.2.1/conf# vim mapred-site.xml
<?xml version="1.0"?>
<?xml-stylesheet type="text/xsl" href="configuration.xsl"?>
<!-- Put site-specific property overrides in this file. -->
<configuration>
<property>
<name>mapred.job.tracker</name>
<value>zhxfei-vm:9001</value>
</property>
</configuration>
给hadoop设置JAVA_HOME环境变量
root@zhxfei-vm:/opt/hadoop-1.2.1/conf# vim hadoop-env.sh
# Set Hadoop-specific environment variables here.
# The only required environment variable is JAVA_HOME. All others are
# optional. When running a distributed configuration it is best to
# set JAVA_HOME in this file, so that it is correctly defined on
# remote nodes.
# The java implementation to use. Required.
export JAVA_HOME=/usr/lib/jvm/java-7-openjdk-amd64
如果没有SSHD服务的话需自己安装openssh-server的,在启动Hadoop的时候需要与其进行连接时需要ssh协议的支持。安装之后可以查看22端口是否开放,开放之后配置ssh免登陆
生成ssh免登陆密钥, 执行完这个命令后,会生成两个文件id_rsa(私钥)、id_rsa.pub(公钥)将公钥拷贝到要免登陆的机器上,由于搭建的是伪分布式所以直接在本地:
ssh-keygen -t rsa
cat ~/.ssh/id_rsa.pub >> ~/.ssh/authorized_keys
之后如果发现不能启动的话可以检查iptables是否放行22端口。
安装错误主要靠错误信息进行排错,对了记得刷新配置:sourse /etc/profile
安装完成之后可以用hadoop的启动脚本 start-all.sh,执行之后使用java的jps查看hadoop是否正常运行NameNode,SecondaryNameNode,DataNode,JobTracker,TaskTracker是否正常运行即可
。操作如下:
root@zhxfei-vm:/opt/hadoop-1.2.1/conf$ start-all.sh
starting namenode, logging to /opt/hadoop-1.2.1/libexec/../logs/hadoop-root-namenode-zhxfei-vm.out
localhost: starting datanode, logging to /opt/hadoop-1.2.1/libexec/../logs/hadoop-root-datanode-zhxfei-vm.out
localhost: starting secondarynamenode, logging to /opt/hadoop-1.2.1/libexec/../logs/hadoop-root-secondarynamenode-zhxfei-vm.out
starting jobtracker, logging to /opt/hadoop-1.2.1/libexec/../logs/hadoop-root-jobtracker-zhxfei-vm.out
localhost: starting tasktracker, logging to /opt/hadoop-1.2.1/libexec/../logs/hadoop-root-tasktracker-zhxfei-vm.out
root@zhxfei-vm:/opt/hadoop-1.2.1/conf$ jps
15962 SecondaryNameNode
16202 TaskTracker
16252 Jps
15671 NameNode
16056 JobTracker
15819 DataNode
HDFS原理
HDFS的组成
在hadoop伪分布式环境中,SecondaryNameNode和NameNode还有DataNode是运行在一台主机上的进程,用进程来模拟主机,而一个典型1.0版本的HDFS集群中,由一个namenode和一个secondarynode和至少一个Datanode,HDFS的客户端数量没有限制。所有数据都放置在DataNode进程的节点的Block(块)里。但是在hadoop2.0集群中没有SecondaryNameNode,但是在2.0的伪分布式模式中有SecondaryNameNode。
- Namenode:HDFS的大脑,接受client的操作请求,维护着整个HDFS系统的目录树,目录里所有的文件和目录,在内存中保留元数据信息,并将其以FSImage和命名空间镜像的编辑日志保存在本地文件中,每次Namenode启动默认加载最新的命名空间镜像。内存和磁盘中各一份。
- FSImage:命名空间镜像 /文件系统快照,为了防止NameNode所在机器掉电,HDFS的文件系统的目录和元数据信息丢失而对HDFS的相关信息的镜像备份。
- Edits:Edit Log记录client对文件的操作而产生的元数据信息产生的变化。其保存的也是原数据信息,但是是更新的原数据信息。在SecondaryNameNode和NameNode进行交互后,会被清空。
- fstime:保存最近一次checkpoint的时间
以上这些文件是保存在linux的文件系统中。
SecoundaryNameNode:用于定期合并命名空间镜像和对其的编辑日志。不是对NameNode的备份!
DataNode:数据节点。在NameNode的指导下完成I/O任务。所有HDFS的块都存放在DataNode上,对于DataNode来说,块就是一个普通的文件,hadoop1.0默认是64MB,而hadoop2.0默认是128MB。不同于普通文件系统的是,HDFS中,如果一个文件小于一个数据块的大小,并不占用整个数据块存储空间
HDFS的客户端:指用户和HDFS交互的手段,有命令行接口,JAVA API,C语言库,用户空间文件系统等等
HDFS的块
文件系统的块大小只能是磁盘块的整数倍,一般磁盘块是512字节,而EXT3的文件系统的块为4096,HDFS的文件块大小为64MB,和其他文件系统不同的是HDFS小于一个块大小不会占据整个块的空间。块的大小可以被改变,配置项为hdfs-site.xml中的dfs.block.size项,是datanode存储数据的最小单元。
如下:
root@zhxfei-vm:/hadoop/data/current# ls
blk_3597001837970459933 blk_-3850128862716211144_2251.meta blk_-6524268894760927318 blk_-8587672643259394653_2242.meta
blk_3597001837970459933_2252.meta blk_-5563214751032658860 blk_-6524268894760927318_2250.meta dncp_block_verification.log.curr
blk_-3850128862716211144 blk_-5563214751032658860_2253.meta blk_-8587672643259394653 VERSION
HDFS的块大小这么大是为了最小化寻址开销,如果块设置的足够大,从磁盘传输的数据的时间明显大于定位这个块开始的时间。这样传输一个由多个块组成的文件的时间取决于磁盘传输的效率。但是设置的太大的话也不好,太大的话,因为当Job通过MapReduce分成子任务时如果子任务的数量受到预处理的文件的块的数量限制。只有在适量的时候,才嗯那个发挥增加文件系统对高数据的吞吐量。hdfs-site.xml中还可以设置dfs.relication,配置每个HDFS的块在Hadoop集群中保存的份数,默认为3,如果为3的话,Hadoop的默认布局会在HDFS的客户端尽量放置第一个副本,如果客户端在集群之外,则会避免存储太满并随机选取一个节点放置。第二个副本放置在随机选择的另一个机架上的任意DataNode,第三各副本放置在和第二个副本相同机架随机的另一个不同的DataNode上。这样可以提供很好的数据的冗余性。
元数据存储细节
Metadata(Filename,reliacas,block-ids,id2host……)
对应着:Metadata(/test/a.log,3,{blk_1,blk_2},[{blk_1:[h1,h2,h3]},{blk_2:[h0,h2,h3]}],……)
表示着:/test/a.log一共有3个副本,被分成2个block块,第一个块的三个副本在h1,h2,h3中存放,第二个块在h0,h2,h3中存放。
当client在NameNode拿到元数据信息之后,其会根据就近原则去取块。每个块采用了CRC校验机制,如果出现问题或者校验出错不符合则换块读取,NameNode在收到client的反馈会通知DataNode根据pipeline对那个损坏的块进行重新的备份。
NameNode和SecondaryNameNode
NameNode的工作特点:Namenode始终在内存中保存metedata,用于处理“读请求”
到有“写请求”到来时,namenode会首先写editlog到磁盘,即向edits文件中写日志,成功返回后,才会修改内存,并且向客户端返回
Hadoop会维护一个fsimage文件,也就是namenode中metedata的镜像,但是fsimage不会随时与namenode内存中的metedata保持一致,而是每隔一段时间通过合并edits文件来更新内容。Secondary namenode就是用来合并fsimage和edits文件来更新NameNode的metedata的。SecondaryNameNode的工作特点,HA的一个解决方案。但不支持热备。配置即可。执行过程:从NameNode上通过HTTP协议下载元数据信息(fsimage,edits),然后把二者合并,生成新的fsimage,在本地保存,并将其推送到NameNode,替换旧的fsimage.默认在安装在NameNode节点上
其交互如下:
1.SecondaryNameNode引导NameNode切换Edit Log文件,生成Edit Log.New并开始更新新的内容写进Edit Log.New
2.SecondaryNameNode将NameNode的FSImage和Edit Log文件复制到本地的检查点目录。
3.SecondaryNameNode载入FSImage文件,回放Edit Log文件将其合并FSImage,并将新的FSImage文件压缩后写入磁盘。
4.SecondaryNameNode将新的FSImage文件送回到NameNode,NameNode在接受新的FSImage后直接加载和应用该文件,将旧的FSImage和Edit Log文件删除,并将Edit log.New其更名为Edit Log。
这个过程每个小时即3600s发生一次,或者当超过fs.checkpoint.size即 规定edits文件的最大值则强制checkpoint,不管是否到达最大时间间隔。默认大小是64M。
HDFS的容错机制:
心跳机制:NameNode和DataNode之间维持心跳检测,当由于网络故障之类的原因,导致DataNode发出的心跳包没有被NameNode正常收到时,NameNode不会给那个DataNode分配新的I/O操作并认为那个DataNode上的数据为无效的。因此NameNode会检测文件块的副本数目小于设置的值,若小于则开始自动复制新的副本并分发给其他的DataNode上检测文件块的完整性:HDFS会记录每个新建文件的所有块校验和,当以后在检索这些文件的时候或者从某个节点获取块的时候首先确认校验和是否一致,若不一致则去其他的DataNode中获取该块的副本。
集群的负载均衡:当某个DataNode的空闲大于一个临界值的时候HDFS会从其他DataNode迁移数据过来文件的删除:删除并不是从NameNode中移除命名空间,而是存放在/trash目录中可以随时恢复,直到 hdfs-site.xml 中的配置时间 fs.trash.interval决定,单位为s
HDFS简单操作
Web UI
自Firefox中访问虚拟机的地址和对应的端口号。50070为默认的namenode的端口,50030为默认的jobtracker的端口
HDFS shell
感觉和linux差不多,略过