版权声明:如有转载,还请标明转载地址 https://blog.csdn.net/m0_37937526/article/details/89761571
目录
1 HDFS原理分析
1.1 HDFS有什么动机和目的
1.2 HDFS的系统结构
1.3 数据块——block
1.4 namenode
1.5 datanode
1.6 HDFS数据的写入过程
1.7 HDFS数据的读取过程
2 HDFS配置文件
2.1 HDFS有用的配置文件及说明
2.2 把hadoop配置部署到每台机器上
3 初始化分布式文件系统HDFS
3.1 启动zookeeper
3.2 启动 journalnode
3.3 初始化HA的zookeeper信息
3.4对nn1上的namenode进行格式化
3.5 启动nn1上的namenode并观察日志文件
3.6 第二个namenode同步第一个namenode状态
3.7 在nn2上启动namenode
3.8 启动ZKFC
3.9 启动datanode
3.10 测试新建的HDFS是否有问题
4 已经初始化分布式文件系统HDFS,怎么启动和关闭
5 带HA的HDFS都包括哪些进程
1 HDFS原理分析
HDFS是Hadoop Distribute File System 的简称,也就是Hadoop的一个分布式文件系统。
1.1 HDFS有什么动机和目的
1)提供较高的容错率,因为数据有备份,通过机架感知策略,namenode会尽量将数据的复本放到不同的机架上,所以小规模的宕机不影响数据的存储。
2)可以使用低成本的硬件搭建一个分布式文件系统。
3)能提供大规模的数据存储,上TB、PB级的规模。
4)高吞吐的数据访问,获得一个完整的数据可以从多个机器上同时读取。
f1.txt ----> 100M 存到hdfs上
先确定hdfs一个块的单位,如果一个块的单位是64M
100M 文件 会分成 两块。
f1.txt ---> f1.txt-1 :block1--64M
f1.txt-2: block2--36M
5)计算时数据读取的方式多采用本地化方式,如果本地化方式不满足则采用临近网络的方式,这也是通过机架感知策略。
机架感知策略的实现机制
默认情况下,Hadoop机架感知是没有启用的,需要在NameNode机器的hadoop-site.xml里配置一个选项,例如:
<property>
<name>topology.script.file.name</name>
<value>/path/to/script</value>
</property>
这个配置选项的value指定为一个可执行程序,通常为一个脚本,该脚本接受一个参数,输出一个值。接受的参数通常为datanode机器的ip地址,而输出的值通常为该ip地址对应的datanode所在的rackID,例如”/rack1”。Namenode启动时,会判断该配置选项是否为空,如果非空,则表示已经启用机架感知的配置,此时namenode会根据配置寻找该脚本,并在接收到每一个datanode的heartbeat时,将该datanode的ip地址作为参数传给该脚本运行,并将得到的输出作为该datanode所属的机架,保存到内存的一个map中。
1.2 HDFS的系统结构
HA: 高可用
namenode: 是大领导。管理数据块映射;处理客户端的读写请求。一般有一个active状态的namenode,有一个standby状态的namenode
active状态的NameNode负责所有的客户端操作
standby状态的NameNode处于从属地位,维护着数据状态,随时准备切换
journalnode:负责两个状态的namenode进行数据同步,保持数据一致。
ZKFC: 作用是HA自动切换。会将NameNode的active状态信息保存到zookeeper。
datanode: 干活的。负责存储client发来的数据块block;执行数据块的读写操作。
关系:
- datanode启动时要在namenode上注册,当datanode改变时,也要通知namenode。datanode 会定期向NameNode发送心跳,告知NameNode 该节点的datanode是活着的。
- datanode之间可以相互传输数据。
1.3 数据块——block
块的设定要合理。
太大,不适宜计算;太小,占namenode内存
文件188M,
64M一块分3块, 占namenode内存:150*3 = 450字节
1M一块,188块,占namenode内存:150*188 ≈ 30000字节
- 数据块是基本的数据存储单位,一般大小为64M/128M/256M,一个大文件根据数据块的大小,将文件分为若干个块。NameNode存储文件对应的block映射信息;而datanode存储块信息对应的数据。
- 块越小读取的速度就越快,但是整体占用namenode的空间就越大,因为不管块大小一个块所占用的namenode内存存储空间为一般为150字节。
- 一个大文件会被拆分成一个个的块,然后存储于不同的机器。对于大规模的集群会存储在不同的机架上,如果一个文件少于Block大小,那么实际占用的空间为其文件的大小。 60M的文件, 块单位64M,实际存储:60M
- 数据块也是基本的读写单位,类似于磁盘的扇区,每次都是读写一个块。读写多个块就合成了一个文件。
- 为了容错,文件的所有数据块都会有副本,也就是说复制的是数据块而不是单独的一个文件被复制了,默认复制3份,可以在hdft-site.xml里进行配置。
- 副本的数据的存储规则:
① 若client为DataNode节点,那存储block时,规则为:副本1,同client的节点上;副本2,不同机架节点上;副本3,同第二个副本机架的另一个节点上;其他副本随机挑选。
② 若client不为DataNode节点,那存储block时,规则为:副本1,随机选择一个节点上;副本2,不同机架节点上;副本3,同第二个副本机架的另一个节点上;其他副本随机挑选。
1.4 namenode
1)namenode是整个集群的中心,负责安排管理集群中数据的存储并记录存储文件的元数据和负责客户端对文件的访问。
2)存储文件的元数据(metadata),主要包括整个文件系统的目录树、文件名与blockid的映射关系、blockid在哪个datanode上。
3)在运行时把所有的元数据都保存到namenode机器的内存中,所以整个HDFS可存储的文件数受限于namenode的内存大小。
4)一个block 在namenode中对应一条记录。
5)namenode的元数据的镜像文件(fsimage)会保存到本地磁盘,但不保存block具体的位置信息,而是由DataNode注册和运行时进行上报维护。
6)namenode完蛋了,那整个HDFS也就完蛋了,所以要采用冗余的方案来保证NameNode的高可用性。
7)元数据fsimage的保存并不及时那namenode要是宕机了怎么办?
还可以通过HDFS的操作日志记录文件(editlog)来恢复,如果元数据fsimage完整就直接恢复,不完整再用editlog进行补余。
1.5 datanode
1)保存block块对应的具体数据。
2)负责数据的读写和复制操作。
3)datanode启动时会向namenode报告当前存储的数据块信息,也会持续的报告数据块的修改信息。
4)datanode之间会进行互相通信,来完成复制数据块的动作,以保证数据的冗余性。
5)给NameNode发送心跳。
1.6 HDFS数据的写入过程
1)客户端发起数据写入请求,告诉namenode要写入的文件信息;
2)namenode根据你的情况(client端所在位置、文件大小)给你分配写入数据的位置也就是写到那几个机器上;
3)向datanode写入数据;
4)datanode复制数据;
5)复制完成之后,各数据节点向namenode上报block信息;
6)datanode通知客户端已完成;
1.7 HDFS数据的读取过程
1)客户端发起读数据的请求;
2)告诉namenode要读那个文件;
3)namenode返回block信息列表(包括要读取的数据在那个机器上);
4)客户端到指定的机器上读取具体的数据;
5)datanode根据block信息找到数据的存储位置并返回数据给客户端;
6)客户端读完数据之后告诉namenode我已经读取完成;
2 HDFS配置文件
HDFS规划
namenode:nn1.hadoop、nn2.hadoop
datanode:s1.hadoop、s2.hadoop、s3.hadoop
2.1 HDFS有用的配置文件及说明
路径:cd /usr/local/hadoop/etc/hadoop
1)hdfs-site.xml
HA集群需要使用命名空间区分一个HDFS集群。同一个集群中的不同NameNode,使用不同的NameNode ID区分。为了支持所有NameNode使用相同的配置文件,因此在配置参数中,需要把“nameservice ID”作为NameNode ID的前缀。
dfs.nameservices 命名空间的逻辑名称。提供服务的NS(nameservices)逻辑名称,与core-site.xml里的对应。如果有多个HDFS集群,可以配置多个命名空间的名称,使用逗号分开即可。
<property>
<name>dfs.nameservices</name>
<value>ns1</value>
<description>提供服务的NS逻辑名称,与core-site.xml里的对应</description>
</property>
dfs.ha.namenodes.[nameservice ID] 命名空间中所有NameNode的唯一标示名称。可以配置多个,使用逗号分隔。该名称是可以让DataNode知道每个集群的所有NameNode。当前,每个集群最多只能配置两个NameNode。
<property>
<name>dfs.ha.namenodes.ns1</name>
<value>nn1,nn2</value>
<description>列出该逻辑名称下的NameNode逻辑名称</description>
</property>
dfs.namenode.rpc-address.[nameservice ID].[name node ID] 每个namenode监听的RPC地址。
dfs.namenode.http-address.[nameservice ID].[name node ID] 每个namenode监听的http地址。
<!--主要的-->
<property>
<name>dfs.namenode.rpc-address.ns1.nn1</name>
<value>nn1.hadoop:9000</value>
<description>指定NameNode的RPC位置</description>
</property>
<!--主要的-->
<property>
<name>dfs.namenode.http-address.ns1.nn1</name>
<value>nn1.hadoop:50070</value>
<description>指定NameNode的Web Server位置</description>
</property>
<!--主要的-->
<property>
<name>dfs.namenode.rpc-address.ns1.nn2</name>
<value>nn2.hadoop:9000</value>
<description>指定NameNode的RPC位置</description>
</property>
<!--主要的-->
<property>
<name>dfs.namenode.http-address.ns1.nn2</name>
<value>nn2.hadoop:50070</value>
<description>指定NameNode的Web Server位置</description>
</property>
RPC(Remote Procedure Call Protocol)
远程过程调用协议。一个通俗的描述是:客户端在不知道调用细节的情况下,调用存在于远程计算机上的某个对象,就像调用本地应用程序中的对象一样。
主要配置说明
name |
value |
description |
dfs.datanode.data.dir |
/data1/dfs,/data2/dfs,/data3/dfs,/data4/dfs,/data5/dfs,/data6/dfs |
datanode本地文件存放地址 |
dfs.replication |
3 |
文件复本数
一个文件,可在其他机器共存放3个副本,保证一个文件不只是在一台机器上 ,体现高可用性 |
dfs.namenode.name.dir |
/data1/dfsname,/data2/dfsname,/data3/dfsname |
namenode本地文件存放地址 |
dfs.support.append |
TRUE |
是否支持追加,但不支持并发线程往里追加 |
dfs.permissions.enabled |
FALSE |
是否开启目录权限,自己用建议不开启 |
dfs.nameservices |
ns1 |
提供服务的NS逻辑名称,与core-site.xml里的对应,可以配置多个命名空间的名称,使用逗号分开即可。 |
dfs.ha.namenodes.[nameservice ID] |
nn1,nn2 |
命名空间中所有NameNode的唯一标示名称。可以配置多个,使用逗号分隔。该名称是可以让DataNode知道每个集群的所有NameNode。当前,每个集群最多只能配置两个NameNode。 |
dfs.namenode.rpc-address.ns1.nn1 |
nn1.hadoop:9000 |
指定NameNode的RPC位置 |
dfs.namenode.http-address.ns1.nn1 |
nn1.hadoop:50070 |
指定NameNode的Web Server位置 |
dfs.namenode.rpc-address.ns1.nn2 |
nn2.hadoop:9000 |
指定NameNode的RPC位置 |
dfs.namenode.http-address.ns1.nn2 |
nn2.hadoop:50070 |
指定NameNode的Web Server位置 |
|
|
|
dfs.namenode.shared.edits.dir |
qjournal://nn1.hadoop:8485;nn2.hadoop:8485/ns1 |
指定用于HA存放edits的共享存储,通常是namenode的所在机器 |
dfs.journalnode.edits.dir |
/data/journaldata/ |
journaldata服务存放文件的地址 |
|
fs.trash.interval |
2880 |
垃圾回收周期,单位分钟 |
dfs.blocksize |
134217728 |
块的大小 |
dfs.datanode.du.reserved |
2147483648 |
每个存储卷保留用作其他用途的磁盘大小 |
dfs.datanode.fsdataset.volume.choosing.policy |
org.apache.hadoop.hdfs.server.datanode.fsdataset.AvailableSpaceVolumeChoosingPolicy |
datanode数据副本存放的磁盘选择策略,
有2种方式一种是轮询方式
(org.apache.hadoop.hdfs.server.datanode.fsdataset.RoundRobinVolumeChoosingPolicy,为默认方式),
另一种为选择可用空间足够多的磁盘存储方式
(org.apache.hadoop.hdfs.server.datanode.fsdataset.AvailableSpaceVolumeChoosingPolicy) |
dfs.datanode.available-space-volume-choosing-policy.balanced-space-threshold |
2147483648 |
当选择可用空间足够多的磁盘存储方式才生效,hdfs计算最大可用空间-最小可用空间的差值,如果差值小于此配置,则选择轮询方式存储 |
2)core-site.xml
主要配置说明
name |
value |
description |
io.native.lib.available |
TRUE |
开启本地库支持 |
fs.defaultFS |
hdfs://ns1 |
客户端连接HDFS时,默认的路径前缀。默认文件服务的协议和NS(nameservices)逻辑名称,和hdfs-site里的对应此配置替代了1.0里的fs.default.name |
io.compression.codecs |
org.apache.hadoop.io.compress.GzipCodec,org.apache.hadoop.io.compress.DefaultCodec,org.apache.hadoop.io.compress.BZip2Codec,org.apache.hadoop.io.compress.SnappyCodec |
相应编码的操作类,用逗号分隔 |
ha.zookeeper.quorum |
nn1.hadoop:2181,nn2.hadoop:2181,s1.hadoop:2181 |
HA使用的zookeeper地址,用逗号分隔 |
3)hadoop-env.sh
HADOOP_CLASSPATH:hadoop的classpath
JAVA_LIBRARY_PATH:java加载本地库的地址
HADOOP_HEAPSIZE:java虚拟机使用的最大内存
HADOOP_OPTS:hadoop启动公用参数
HADOOP_NAMENODE_OPTS:namenode专用参数
HADOOP_DATANODE_OPTS:datanode专用参数
HADOOP_CLIENT_OPTS:hadoop client专用参数
4)slaves
slaves文件里面记录的是集群里所有DataNode的主机名
hadoop-daemons.sh 中用到了 slaves 文件
注意:配置文件里的host改成你自己的
2.2 把hadoop配置部署到每台机器上
1)把hadoop配置分发到每个机器上,并解压
#将配置文件压缩包上传到~hadoop/up
cd ~/up
rz
#hadoop配置文件地址
ll /usr/local/hadoop/etc/hadoop/
#批量备份hadoop的配置
./ssh_all.sh mv /usr/local/hadoop/etc/hadoop /usr/local/hadoop/etc/hadoop_back
# 检查备份
./ssh_all.sh ls /usr/local/hadoop/etc
#批量将自定义的配置拷贝到/tmp 目录下
./scp_all.sh ../up/hadoop.tar.gz /tmp/
#批量将自定义配置 压缩包解压到/usr/local/hadoop/etc/
./ssh_all.sh tar -xzf /tmp/hadoop.tar.gz -C /usr/local/hadoop/etc/
#批量检查配置是否正确解压
./ssh_all.sh ls /usr/local/hadoop/etc
# 将配置文件修改下
vim /usr/local/hadoop/etc/hadoop/hdfs-site.xml
# 分发下
./scp_all.sh /usr/local/hadoop/etc/hadoop/hdfs-site.xml /usr/local/hadoop/etc/hadoop
# 检查
./ssh_all.sh 'ls -l /usr/local/hadoop/etc/hadoop | grep hdfs-site'
2)批量修改/usr/local/hadoop/etc/hadoop目录下的文件权限为770
# 修改每个机器上的配置文件地址权限
./ssh_all.sh chmod -R 770 /usr/local/hadoop/etc/hadoop
3 初始化分布式文件系统HDFS
步骤:
1)启动zookeeper
2)启动 journalnode 2台
3)启动zookeeper客户端,初始化HA的zookeeper信息
4)对nn1上的namenode进行格式化
5)启动nn1上的namenode
6)在nn2上 同步namenode
7)启动nn2上的namenode
8)启动ZKFC 2台
9)启动datanode 3台
3.1 启动zookeeper
#启动zookeeper
./ssh_all_zookeeper.sh /usr/local/zookeeper/bin/zkServer.sh start
#查看zookeeper运行的状态
./ssh_all_zookeeper.sh /usr/local/zookeeper/bin/zkServer.sh status
3.2 启动 journalnode
/usr/local/hadoop/sbin 里
cd /usr/local/hadoop/logs/ hadoop 相关服务日志文件地址
less hadoop-hadoop-journalnode-nn1.hadoop.log
# 在每个要运行的机器上执行 nn1 nn2
hadoop-daemon.sh start journalnode
# 查看启动 nn1 的日志
less /usr/local/hadoop/logs/hadoop-hadoop-journalnode-nn1.hadoop.log
启动后会在 /data目录下创建journaldata目录
查看端口是否纯在
netstat -apn |grep 8485
#在nn1上启动journalnode
hadoop-daemon.sh start journalnode
#在nn2上启动journalnode
hadoop-daemon.sh start journalnode
筛选某列所有数据:
awk工作流程:
读入有'\n'换行符分割的一条记录,然后将记录按指定的域分隔符划分域,填充域,
$0则表示所有域;
$1表示第一个域;
$n表示第n个域;
默认域分隔符是"空白键" 或 "[tab]键"
3.3 初始化HA的zookeeper信息
#启动zkclient,并连接zookeeper集群
/usr/local/zookeeper/bin/zkCli.sh -server nn1.hadoop:2181,nn2.hadoop:2181,s1.hadoop:2181
#在nn1克隆会话,用hadoop用户执行下面命令,初始化HA的zookeeper信息
hdfs zkfc -formatZK
通过zookeeper客户端查看结点
在nn1上执行 hdfs zkfc -formatZK 初始化HA的zookeeper信息
初始化后,通过zookeeper客户端查看结点
3.4对nn1上的namenode进行格式化
初始化一些目录和文件。
# 在nn1上执行
hadoop namenode -format
3.5 启动nn1上的namenode并观察日志文件
# 在nn1上执行
hadoop-daemon.sh start namenode
查看日志:
less /usr/local/hadoop/logs/hadoop-hadoop-namenode-nn1.hadoop.log
3.6 第二个namenode同步第一个namenode状态
# 在nn2上执行
hadoop namenode -bootstrapStandby
3.7 在nn2上启动namenode
# 在nn2上执行
hadoop-daemon.sh start namenode
vim /usr/local/hadoop-2.7.3/logs/hadoop-hadoop-namenode-nn2.hadoop.log 观察日志
3.8 启动ZKFC
在 nn1 和 nn2 分别启动ZKFC,这时两个namenode,一个变成active,一个变成standby
zkfc作用:HA自动切换。
hadoop-daemon.sh start zkfc
active
standby
在自己的windows电脑上配置好hosts
C:\Windows\System32\drivers\etc\hosts
通过网页查看
在任何机器上执行hdfs haadmin -getServiceState <namenode_id>可查看HA状态
hdfs haadmin -getServiceState nn1
hdfs haadmin -getServiceState nn2
3.9 启动datanode
在nn1上执行hadoop-daemons.sh start datanode 启动s1 s2 s3上的datanode服务,注意这里是hadoop-daemons.sh而不是hadoop-daemon.sh
也可以在s1, s2, s3 三台上分别执行这个命令
hadoop-daemons.sh start datanode
可以通过:less /usr/local/hadoop/logs/hadoop-hasoop-s1.hadoop.log 查看日志启动情况 (在s页面上)
也可通过页面查看:
启动完成后看http://nn1.hadoop:50070页面的状态,查看集群的存储情况和节点信息
http://nn1.hadoop:50070 nn1节点页面
http://nn2.hadoop:50070 nn2节点页面
介绍页面内容
3.10 测试新建的HDFS是否有问题
hadoop fs -mkdir /data (等于 hadoop fs -mkdir hdfs://ns1/data) 在hdfs上创建一下data目录
hadoop fs -put ./hadoop.tar.gz /data/ 向hdfs上传一个文件进行测试
tail -f /usr/local/hadoop/logs/hadoop-hadoop-datanode-s2.hadoop.log 查看数据节点的datanode日志(在datanode机器上查看)
在web页面上查看文件
因为有3个副本所以每台机器上使用的容量是一样的
4 已经初始化分布式文件系统HDFS,怎么启动和关闭
#启动分布式文件系统HDFS
/usr/local/hadoop/sbin/start-dfs.sh
#关闭分布式文件系统HDFS
/usr/local/hadoop/sbin/stop-dfs.sh
关闭
5 带HA的HDFS都包括哪些进程
#查看每个机器上的java进程
./ssh_all.sh jps
#查看详细进程信息
ps -aux | grep java
从里面查看启动信息是否有你自己的配置,就是你配置的hadoop-env.sh里的信息
注意HA不能切换是因为nn1和nn2的没有安装fuser,可在zkfc日志中看到
先用root用户 ,安装在nn1和nn2上执行
yum -y install psmisc
重启hdfs集群,在执行HA切换。
切换前
切换后: