淘先锋技术网

首页 1 2 3 4 5 6 7

HDFS 完全分布式搭建

分布式规划:

node1

node2

node3

node4

NameNode

SecondaryNameNode

DataNode-1

DataNode-2

DataNode-3

搭建步骤

1、免秘钥设置

0、免密钥设置

a、首先在四台服务器上都要执行:ssh-keygen  -t  dsa  -P  ''  -f  ~/.ssh/id_dsa

b、在node1上将node1 的公钥拷贝到authorized_keys中:

cat  ~/.ssh/id_dsa.pub  >>  ~/.ssh/authorized_keys

将该文件拷贝给node2:scp  ~/.ssh/authorized_keys   node2:/root/.ssh/

c、在node2中将node2的公钥追加到authorized_keys中:

cat  ~/.ssh/id_dsa.pub  >>  ~/.ssh/authorized_keys

将该文件拷贝给node3:scp  ~/.ssh/authorized_keys   node3:/root/.ssh/

d、在node3中将node3的公钥追加到authorized_keys中:

cat  ~/.ssh/id_dsa.pub  >>  ~/.ssh/authorized_keys

将该文件拷贝给node4:scp  ~/.ssh/authorized_keys   node4:/root/.ssh/

e、在node4中将node4的公钥追加到authorized_keys中:

cat  ~/.ssh/id_dsa.pub  >>  ~/.ssh/authorized_keys

将该文件拷贝给node1、node2、node3:scp  ~/.ssh/authorized_keys   node[123]:/root/.ssh//

2、通过scp拷贝

首先将node1中的hadoop-2.6.5/share/doc删除

再删除$HADOOP_HOME/logs/*

将/opt/hadoop-2.6.5 scp到node2、node3、node4的对应目录中

scp -r hadoop-2.6.5/ node2:`pwd`

scp -r hadoop-2.6.5/ node3:`pwd`

scp -r hadoop-2.6.5/ node4:`pwd`

将/root/下的jdk.rpm scp到node2、node3、node4的对应目录中

scp jdk-8u191-linux-x64.rpm node2:`pwd`

scp jdk-8u191-linux-x64.rpm node3:`pwd`

scp jdk-8u191-linux-x64.rpm node4:`pwd`

3、配置

在node2、node3、node4上安装jdk并配置profile文件

rpm -ivh jdk-8u191-linux-x64.rpm

/etc/profile

将node1的/etc/profile拷贝到node2、node3、node4上并执行. /etc/profile

修改node1:/opt/hadoop-2.6.5/etc/hadoop/中的slaves

指定datanode的位置

node2

node3

node4

修改node1:/opt/hadoop-2.6.5/etc/hadoop/中的hdfs-site.xml

指定SNN的位置

<property>

        <name>dfs.namenode.secondary.http-address</name>

        <value>node2:50090</value>

</property>

<property>

        <name>dfs.replication</name>

        <value>2</value>

</property>

修改node1:/opt/hadoop-2.6.5/etc/hadoop/中的core-site.xml

<property>

        <name>hadoop.tmp.dir</name>

        <value>/var/bjsxt/hadoop/full</value>

</property>

将这四个文件core-site.xml/hdfs-site.xml/slaves/hadoop-env.sh在四台服务器之间共享

scp  /opt/hadoop-2.6.5/etc/hadoop/*  node[234]:/opt/hadoop-2.6.5/etc/hadoop

4、格式化并启动

格式化

在node1上执行:hdfs  namenode  -format

启动即可(该命令在四台服务器上哪一台执行都可以)

start-dfs.sh

5、停止

stop-dfs.sh

Hadoop 3.X 新特性(了解)

1、将默认的最低jdk从7升级到8

2、纠删码可以将3倍副本占据的空间压缩到1.5倍,并保持3倍副本的容错。由于在读取数据的时候需要进行额外的计算,用于存储使用不频繁的数据

3、通过扩展YARN的资源类型,支持CPU和内存之外的其他资源,如GPU、FPGA、软件许可证、本地存储等。

4、重写了hadoop中的shell脚本,修复了很多长期存在的bug并添加了新特性。有一些改进兼容老版本,有一些不兼容

5、对map阶段的输出收集器增加了本地实现,对于洗牌密集型工作,可以提高30%以上的性能。

6、hadoop2.x中NameNode的HA包含一个active的NameNode和一个Standby的NameNode。解决了系统中NameNode的单点故障问题。在hadoop3中允许多个standby状态的NameNode以达到更高级别容错的目的。

7、以前,多个Hadoop服务的默认端口位于Linux临时端口范围(32768-61000)。 这意味着在启动时,由于与另一个应用程序的冲突,服务有时无法绑定到端口。这些冲突的端口已移出临时范围,影响NameNode,Secondary NameNode,DataNode和KMS。

8、Hadoop现在支持与Microsoft Azure Data Lake和Aliyun对象存储系统的集成,作为替代Hadoop兼容的文件系统。

9、单个DataNode管理多个磁盘。 在正常写入操作期间,磁盘将被均匀填充。 但是,添加或替换磁盘可能会导致DataNode内的严重数据偏斜。 旧的HDFS平衡器不能处理,旧的HDFS平衡器处理DN之间而非内部的数据偏斜。

10、对Hadoop守护进程以及MapReduce任务的堆管理做了一系列更改。现在可以根据主机的内存大小进行自动调整,并且不推荐使用HADOOP_HEAPSIZE变量。简化了map和reduce任务堆空间的配置,在任务中不再需要以java选项的方式进行指定

11、为Amazon S3存储的S3A客户端添加了一个可选功能:能够将DynamoDB表用于文件和目录元数据的快速一致存储。

12、HDFS基于路由器的联邦添加了一个RPC路由层,该层提供多个HDFS命名空间的联合视图。 这与现有的ViewFs和HDFS联合功能类似,不同之处在于安装表由路由层而不是客户端在服务器端进行管理, 简化了对现有HDFS客户端对联邦群集的访问。

Hadoop Federation(了解)联邦

NameNode需要多少内存

问题:NameNode需要多大的内存?

业界看法:1GB内存放1,000,000block元数据。

200个节点的集群中每个节点有24TB存储空间,block大小为128MB,block复制因子为3,能存储大概2000,000个block(或更多):200×24,000,000MB/(128MB×3)。此时,NameNode内存大概需要12000MB。

一万个节点的集群需要多大的NameNode的内存?

HDFS组成

1、Namespace

    a) 包括目录,文件和block块。

    b) 支持所有跟文件系统命名空间相关的操作

         如:创建、删除、修改和列出文件及目录。

2、Block存储服务包含两部分:

    a) NameNode中的block块管理

        i. 通过心跳机制和注册机制提供了对DataNode集群的管理。

        ii. 处理block块报告,管理block块的位置。

        iii. 提供跟block块相关的操作,如:创建、修改、删除和查询block块的位置。

        iv. 管理block副本如何放置,当副本数少于指定值之后增加副本,当副本数多余指定值之后删除副本。

    b) 存储:

        在DataNode本地文件系统中存储block块,并提供读/写访问。

1、NameNode节点之间是相互独立的联邦的关系,即它们之间不需要协调服务。

2、DataNode向集群中所有的NameNode注册,发送心跳和block块列表报告,处理来自NameNode的指令。

3、用户可以使用ViewFs创建个性化的命名空间视图,ViewFs类似于在Unix/Linux系统中的客户端挂载表

VERSION

namespaceID  用于标记namenode的ID

blockpoolID  用于标记block存储池子的ID

clusterID  集群的ID

hadopp-env.sh

配置JAVA_HOME

core-site.xml配置:

<configuration>

  <property>

    <name>fs.defaultFS</name>

    <value>viewfs://ClusterX</value>

  </property>

  <property>

    <name>fs.viewfs.mounttable.ClusterX.link./data</name>

    <value>hdfs://node1:8020/data</value>

  </property>

  <property>

    <name>fs.viewfs.mounttable.ClusterX.link./project</name>

    <value>hdfs://node1:8020/project</value>

  </property>

  <property>

    <name>fs.viewfs.mounttable.ClusterX.link./user</name>

    <value>hdfs://node2:8020/user</value>

  </property>

  <property>

    <name>fs.viewfs.mounttable.ClusterX.link./tmp</name>

    <value>hdfs://node2:8020/tmp</value>

  </property>

<!--  <property>

    <name>fs.viewfs.mounttable.ClusterX.linkFallback</name>

    <value>hdfs://node2:8020/home</value>

  </property>

-->

  <property>

    <name>hadoop.tmp.dir</name>

    <value>/var/bjsxt/hadoop/federation</value>

  </property>

</configuration>

hdfs-site.xml

<configuration>

  <property>

    <name>dfs.replication</name>

    <value>2</value>

  </property>

  <property>

    <name>dfs.blocksize</name>

    <value>1048576</value>

  </property>

  <property>

    <name>dfs.nameservices</name>

    <value>ns1,ns2</value>

  </property>

  <property>

    <name>dfs.namenode.rpc-address.ns1</name>

    <value>node1:8020</value>

  </property>

  <property>

    <name>dfs.namenode.http-address.ns1</name>

    <value>node1:50070</value>

  </property>

  <property>

    <name>dfs.namenode.secondary.http-address.ns1</name>

    <value>node3:50090</value>

  </property>

  <property>

    <name>dfs.namenode.rpc-address.ns2</name>

    <value>node2:8020</value>

  </property>

  <property>

    <name>dfs.namenode.http-address.ns2</name>

    <value>node2:50070</value>

  </property>

  <property>

    <name>dfs.namenode.secondary.http-address.ns2</name>

    <value>node4:50090</value>

  </property>

</configuration>

slaves

node2

node3

node4

格式化node1

$HADOOP_PREFIX_HOME/bin/hdfs namenode -format -clusterId myviewfs

格式化node2

$HADOOP_PREFIX_HOME/bin/hdfs namenode -format -clusterId myviewfs

在格式化node1和node2上的namenode时候,需要指定clusterId,并且两个格式化的时候这个clusterId要一致,两个namenode具有相同的clusterId,它们在一个集群中,它们是联邦的关系。

start-dfs.sh

stop-dfs.sh

优点

  1. 通过多个namenode/namespace把元数据的存储和管理分散到多个节点中,使得namenode/namespace可以通过增加机器来进行水平扩展
  2. 能把单个namenode的负载分散到多个节点中,在HDFS数据规模较大的时候不会也降低HDFS的性能。
  3. 可以通过多个namespace来隔离不同类型的应用,把不同类型应用的HDFS元数据的存储和管理分派到不同的namenode中。

Hadoop HA

HDFS  2.x

解决HDFS 1.0中单点故障内存受限问题,联邦     HA

HDFS2.x中Federation和HA分离,HA只能有两个NameNode

解决单点故障

HDFS HA:通过主备NameNode解决

如果主NameNode发生故障,则切换到备NameNode上。

解决内存受限问题

HDFS Federation(联邦);水平扩展,支持多个NameNode;

(1)所有NameNode共享所有DataNode存储资源

(2)每个NameNode分管一部分目录;

 

手动HA

fsimage+edits log需要

由StandbyNameNode做合并工作

fsimage推送的时机可以通过参数来调整:

dfs.namenode.checkpoint.period    1小时

dfs.namenode.checkpoint.txns      100 0000事务

dfs.namenode.checkpoint.check.period   3s

dfs.namenode.num.checkpoints.retained

dfs.ha.tail-edits.period

  1. 一个NameNode进程处于Active状态,另1个NameNode进程处于Standby状态。Active的NameNode负责处理客户端的请求。
  2. Active的NN修改了元数据之后,会在JNs的半数以上的节点上记录这个日志。Standby状态的NameNode会监视任何对JNs上edit log的更改。一旦edits log出现更改,Standby的NN就会根据edits log更改自己记录的元数据。
  3. 当发生故障转移时,Standby主机会确保已经读取了JNs上所有的更改来同步它本身记录的元数据,然后由Standby状态切换为Active状态。
  4. 为了确保在发生故障转移操作时拥有相同的数据块位置信息,DNs向所有NN发送数据块位置信息和心跳数据。
  5. JNs只允许一台NameNode向JNs写edits log数据,这样就能保证不会发生“脑裂”。

自动HA

 

总结

主备NameNode

解决单点故障(属性,位置)à元数据

主NameNode对外提供服务,备NameNode同步主NameNode元数据,以待切换

所有DataNode同时向两个NameNode汇报数据块信息(位置)

JNN:集群(属性)同步edits log

standby:备,完成了edits.log文件的合并产生新的image,推送回ANN

两种切换选择

手动切换:通过命令实现主备之间的切换,可以用HDFS升级等场合

自动切换:基于Zookeeper实现

基于Zookeeper自动切换方案

ZooKeeper Failover Controller:监控NameNode健康状态,

并向Zookeeper注册NameNode

NameNode挂掉后,ZKFC为NameNode竞争锁,获得ZKFC 锁的NameNode变为active

zookeeper的分布式锁,keepalived

Hadoop HA 集群搭建


规划

搭建步骤

如何让ssh不提示fingerprint信息,然后输入yes或者no

/etc/ssh/ssh_config(客户端配置文件)  区别于sshd_config(服务端配置文件)

 

1、zookeeper集群搭建

         a) 将zookeeper.tar.gz上传到node2、node3、node4

         b) 解压到/opt

                   tar -zxf zookeeper-3.4.6.tar.gz -C /opt

         c) 配置环境变量:

                   export ZOOKEEPER_PREFIX=/opt/zookeeper-3.4.6

                   export PATH=$PATH:$ZOOKEEPER_PREFIX/bin

                   然后. /etc/profile让配置生效

         d) 到$ZOOKEEPER_PREFIX/conf下

                   复制zoo_sample.cfg为zoo.cfg

                   cp zoo_sample.cfg  zoo.cfg

         e) 编辑zoo.cfg

                   添加如下行:

                   server.1=node2:2881:3881

                   server.2=node3:2881:3881

                   server.3=node4:2881:3881

                  

                   修改

                   dataDir=/var/bjsxt/zookeeper/data

         f) 创建/var/bjsxt/zookeeper/data目录,并在该目录下放一个文件:myid

           在myid中写下当前zookeeper的编号

           mkdir -p /var/bjsxt/zookeeper/data

           echo 3 > /var/bjsxt/zookeeper/data/myid

2181  用户客户端连接zk集群的端口

zkCli.sh 客户端启动脚本

zkServer.sh 服务端启动脚本

mysql -uroot -p123456

mysqld 服务端

         g) 将/opt/zookeeper-3.4.6通过网络拷贝到node2、node3上

                   scp -r zookeeper-3.4.6/ node2:/opt

                   scp -r zookeeper-3.4.6/ node3:/opt

         h) 在node2和node3上分别创建/var/bjsxt/zookeeper/data目录,

         并在该目录下放一个文件:myid

                   node2:

                   mkdir -p /var/bjsxt/zookeeper/data

                   echo 1 > /var/bjsxt/zookeeper/data/myid

                   node3:

                   mkdir -p /var/bjsxt/zookeeper/data

                   echo 2 > /var/bjsxt/zookeeper/data/myid

        

         i) 启动zookeeper

                   zkServer.sh start 启动zk

zkServer.sh stop  停止zk

zkServer.sh status  查看zk状态

                   zkServer.sh start|stop|status

         j) 关闭zookeeper

                   zkServer.sh stop

         l) 连接zookeeper

                   zkCli.sh     node2、node3、node4都可以

         m) 退出zkCli.sh命令

                   quit

  1. hadoop配置

一律在node1上操作,做完后scp到node2、node3、node4

hadoop-env.sh配置JDK

core-site.xml

        

         <configuration>

           <property>

                   <name>fs.defaultFS</name>

                   <value>hdfs://mycluster</value>   hdfs://node1:9000

           </property>

           <property>

                   <name>hadoop.tmp.dir</name>

                   <value>/var/bjsxt/hadoop/ha</value>

           </property>

           <!-- 指定每个zookeeper服务器的位置和客户端端口号 -->

           <property>

                    <name>ha.zookeeper.quorum</name>

                    <value>node2:2181,node3:2181,node4:2181</value>

            </property>

         </configuration>

        

       hdfs-site.xml

        

         <configuration>

           <!-- 指定block默认副本个数 -->

           <property>

                   <name>dfs.replication</name>

                   <value>2</value>

           </property>

           <!-- 用于解析fs.defaultFS中hdfs://mycluster中的mycluster地址 -->

           <property>

                   <name>dfs.nameservices</name>

                   <value>mycluster</value>

           </property>

           <!-- mycluster下面由两个namenode服务支撑 -->

           <property>

                   <name>dfs.ha.namenodes.mycluster</name>

                   <value>nn1,nn2</value>

           </property>

           <!--指定nn1的地址和端口号,发布的是一个hdfs://的服务-->

           <property>

                   <name>dfs.namenode.rpc-address.mycluster.nn1</name>

                   <value>node1:8020</value>

           </property>

           <property>

                   <name>dfs.namenode.rpc-address.mycluster.nn2</name>

                   <value>node2:8020</value>

           </property>

           <!--指定三台journal服务器的地址-->

           <property>

                   <name>dfs.namenode.shared.edits.dir</name>

                   <value>qjournal://node1:8485;node2:8485;node3:8485/mycluster</value>

           </property>

           <!-- 指定客户端查找active的namenode的策略:

           会给所有namenode发请求,以决定哪个是active的 -->

           <property>

                   <name>dfs.client.failover.proxy.provider.mycluster</name>

                   <value>org.apache.hadoop.hdfs.server.namenode.ha.ConfiguredFailoverProxyProvider</value>

           </property>

           <!--在发生故障切换的时候,ssh到对方服务器,将namenode进程kill掉  kill -9  55767-->

                   <property>

                     <name>dfs.ha.fencing.methods</name>

                     <value>sshfence</value>

                   </property>

                   <property>

                     <name>dfs.ha.fencing.ssh.private-key-files</name>

                     <value>/root/.ssh/id_dsa</value>

                   </property>

           <!-- 指定journalnode在哪个目录存放edits log文件 -->

           <property>

                   <name>dfs.journalnode.edits.dir</name>

                   <value>/var/bjsxt/hadoop/ha/jnn</value>

           </property>

         <!--启用自动故障切换-->

         <property>

            <name>dfs.ha.automatic-failover.enabled</name>

            <value>true</value>

          </property>

         </configuration>

3、启动ha的hadoop

先同步配置文件到node2、node3、node4

scp -r $HADOOP_HOME/etc/hadoop/*   node[234]:/opt/hadoop-2.6.5/etc/hadoop/

        

         0)启动zookeeper集群

         a) 在node1\node2\node3上启动三台journalnode

                   hadoop-daemon.sh start journalnode

         b) 任意选择node1,格式化HDFS

                   hdfs namenode -format

                   格式化后,启动namenode进程

                   hadoop-daemon.sh start namenode

         c) 在另一台node2上同步元数据

                   hdfs namenode -bootstrapStandby

        

         d) 初始化zookeeper上的内容 一定是在namenode节点上。

                   hdfs zkfc -formatZK

        

         e) 启动hadoop集群,可在node1到node4这四台服务器上任意位置执行

                   start-dfs.sh

stop-dfs.sh停止hadoop服务。

如果格式化之后,启动:

         启动三台zk

         随意节点:start-dfs.sh

        

         hadoop-daemon.sh stop namenode

         hadoop-daemon.sh stop zkfc

4、zookeeper操作

         在node2或者node3或者node4上运行

         zkCli.sh

        

         ls /hadoop-ha/mycluster 查看临时文件

         get /hadoop-ha/mycluster/ActiveStandbyElectorLock 查看临时文件的内容

        

         退出zkCli.sh

         quit

        

hdfs dfs -mkdir /user

hdfs dfs -mkdir /user/root

/user/root是用户root家目录

5、停止集群:

         首先

         stop-dfs.sh

         其次,停止zookeeper集群

         node2、node3、node4上执行:

         zkServer.sh stop

(扩展)

用法: haadmin

    [-transitionToActive <serviceId>]

    [-transitionToStandby <serviceId>]

    [-failover [--forcefence] [--forceactive] <serviceId> <serviceId>]

    [-getServiceState <serviceId>]

    [-getAllServiceState]

    [-checkHealth <serviceId>]

    [-help <command>]

可以“hdfs haadmin -help <command>”查看帮助

transitionToActive和transitionToStandby - 将NameNode切换到Active或Standby状态

这两个命令不进行围栏操作,最好少用。最好使用“hdfs haadmin -failover”。

failover – 在指定的两个NameNode之间触发一个故障切换

如果第一个NameNode处于Standby状态,这个命令简单地让第二个NameNode处于Active状态,不报错。如果第一个处于Active状态,则尝试将它置于Standby状态。如果失败了,则fencing method会执行dfs.ha.fencing.methods列表中的下一个命令,直到有一个执行成功。在这之后才会将第二个NameNode转换为Active状态。如果没有fencing method成功,第二个NameNode不会转换为Active状态,同时报错。

getServiceState – 返回指定的NameNode处于Active或Standby状态

连接给定的NameNode并获取它的状态,返回“standby”或“active”到标准输出。这个命令用于定时器作业或监控脚本等需要根据NameNode状态执行不同操作的场合。

getAllServiceState – 返回所有NameNode的状态

连接到所有配置的NameNode,在标准输出为每个NameNode打印“standby”或“active”。

checkHealth – 检查给定NameNode的健康状态

连接到指定的NameNode并检查其健康状态。NameNode会进行自我诊断,包括检查内部服务是否正常运行。如果NameNode运行正常,则返回0,非0表示运行不正常。一般监控的时候使用。

需要注意的是,该命令还没有实现,当前如果不是NameNode宕机,只返回成功。

java客户端操作HDFS

1、windows上部署hadoop包

部署包 win版本

源码包 zip包

lib整合

$HADOOP_PREFIX/share/hadoop/{common,hdfs,mapreduce,yarn,tools}/{lib,.}*.jar    121个jar包

将widows版本hadoop/bin/hadoop.dll  放到 c:/windows/system32下

2、windows环境变量配置

hadoop的bin和sbin目录放PATH中+HADOOP_HOME+HADOOP_USER_NAME=root

3、eclipse插件

安装插件

配置

重启电脑!!!!!!!加载hadoop.dll

创建java project

添加依赖jar

创建源码包

拷贝linux集群中的core-site.xml和hdfs-site.xml到项目的源码包下

程序可以做到本地化读取

input.seek(param);

HDFS本地化读取是一个优势