zookeeper详解
|
|
1.Zookeeper(***必须掌握***)
官方网址:http://zookeeper.apache.org/
Ø 什么是Zookeeper?
l Zookeeper 是 Google 的 Chubby一个开源的实现,是 Hadoop 的分布式协调服务
l 它包含一个简单的原语集,分布式应用程序可以基于它实现同步服务,配置维护和命名服务等
Ø 为什么使用Zookeeper?
l 大部分分布式应用需要一个主控、协调器或控制器来管理物理分布的子进程(如资源、任务分配等)
l 目前,大部分应用需要开发私有的协调程序,缺乏一个通用的机制
l 协调程序的反复编写浪费,且难以形成通用、伸缩性好的协调器
l ZooKeeper:提供通用的分布式锁服务,用以协调分布式应用
Ø Zookeeper能帮我们做什么?
l Hadoop2.0,使用Zookeeper的事件处理确保整个集群只有一个活跃的NameNode,存储配置信息等.
l HBase,使用Zookeeper的事件处理确保整个集群只有一个HMaster,察觉HRegionServer联机和宕机,存储”访问控制列表ACL”等.
Ø Zookeeper的特性
l Zookeeper是简单的
l Zookeeper是富有表现力的
l Zookeeper具有高可用性
l Zookeeper采用松耦合交互方式
l Zookeeper是一个资源库
Ø Zookeeper的安装和配置(单机模式)
一、下载ZooKeeper:
http://labs.renren.com/apache-mirror/zookeeper/zookeeper-3.4.3/zookeeper-3.4.3.tar.gz
解压:tar xzf zookeeper-3.4.3.tar.gz
二、在conf目录下创建一个配置文件zoo.cfg,
tickTime=2000
dataDir=/Users/zdandljb/zookeeper/data
dataLogDir=/Users/zdandljb/zookeeper/dataLog
clientPort=2181
三、启动ZooKeeper的Server:
sh bin/zkServer.sh start, 如果想要关闭,输入:zkServer.sh stop
Ø Zookeeper的安装和配置(集群模式)
一、创建myid文件:
server1机器的内容为:1
server2机器的内容为:2
server3机器的内容为:3
二、在conf目录下创建一个配置文件zoo.cfg
tickTime=2000
dataDir=/Users/zdandljb/zookeeper/data
dataLogDir=/Users/zdandljb/zookeeper/dataLog
clientPort=2181
initLimit=5
syncLimit=2
server.1=server1:2888:3888
server.2=server2:2888:3888
server.3=server3:2888:3888
Ø Zookeeper的安装和配置(伪集群模式)
一、建了3个文件夹,server1 server2 server3,然后每个文件夹里面解压一个zookeeper的下载包
二、进入data目录,创建一个myid的文件,里面写入一个数字,server1,就写一个1,server2对应myid文件就写入2,server3对应myid文件就写个3
三、在conf目录下创建一个配置文件zoo.cfg
tickTime=2000
dataDir=/Users/zdandljb/zookeeper/data
dataLogDir=xxx/zookeeper/server1/
clientPort=2181
initLimit=5
syncLimit=2
server.1=server1:2888:3888
server.2=server2:2888:3888
server.3=server3:2888:3888
Ø Zookeeper的数据模型
l 层次化的目录结构,命名符合常规文件系统规范
l 每个节点在zookeeper中叫做znode,并且其有一个唯一的路径标识
l 节点Znode可以包含数据和子节点,但是EPHEMERAL类型的节点不能有子节点
l Znode中的数据可以有多个版本,比如某一个路径下存有多个数据版本,那么查询这个路径下的数据就需要带上版本
l 客户端应用可以在节点上设置监视器
l 节点不支持部分读写,而是一次性完整读写
Ø Zookeeper的节点
l Znode有两种类型,短暂的(ephemeral)和持久的(persistent)
l Znode的类型在创建时确定并且之后不能再修改
l 短暂znode的客户端会话结束时,zookeeper会将该短暂znode删除,短暂znode不可以有子节点
l 持久znode不依赖于客户端会话,只有当客户端明确要删除该持久znode时才会被删除
l Znode有四种形式的目录节点,PERSISTENT、PERSISTENT_SEQUENTIAL、EPHEMERAL、EPHEMERAL_SEQUENTIAL
Ø Zookeeper的角色
l 领导者(leader),负责进行投票的发起和决议,更新系统状态
l 学习者(learner),包括跟随者(follower)和观察者(observer),follower用于接受客户端请求并向客户端返回结果,在选主过程中参与投票
l Observer可以接受客户端连接,将写请求转发给leader,但observer不参加投票过程,只同步leader的状态,observer的目的是为了扩展系统,提高读取速度
l 客户端(client),请求发起方
Ø Zookeeper的顺序号
l 创建znode时设置顺序标识,znode名称后会附加一个值
l 顺序号是一个单调递增的计数器,由父节点维护
l 在分布式系统中,顺序号可以被用于为所有的事件进行全局排序,这样客户端可以通过顺序号推断事件的顺序
Ø Zookeeper的读写机制
l Zookeeper是一个由多个server组成的集群
l 一个leader,多个follower
l 每个server保存一份数据副本
l 全局数据一致
l 分布式读写
l 更新请求转发,由leader实施
Ø Zookeeper的保证
l 更新请求 顺序进行,来自同一个client的更新请求按其发送顺序依次执行
l 数据更新原子性,一次数据更新要么成功,要么失败
l 全局唯一数据视图,client无论连接到哪个server,数据视图都是一致的
l 实时性,在一定事件范围内,client能读到最新数据
Ø Zookeeper的API接口
l String create(String path, byte[] data,List<ACL> acl, CreateMode createMode)
l Stat exists(String path, boolean watch)
l void delete(String path, int version)
l List<String> getChildren(String path, boolean watch)
l Stat setData(String path, byte[] data, int version)
l byte[] getData(String path, boolean watch, Stat stat)
l void addAuthInfo(String scheme, byte[] auth)
l Stat setACL(String path,List<ACL> acl, int version)
l List<ACL> getACL(String path, Stat stat)
Ø 观察(watcher)
l Watcher 在 ZooKeeper 是一个核心功能,Watcher 可以监控目录节点的数据变化以及子目录的变化,一旦这些状态发生变化,服务器就会通知所有设置在这个目录节点上的 Watcher,从而每个客户端都很快知道它所关注的目录节点的状态发生变化,而做出相应的反应
l 可以设置观察的操作:exists,getChildren,getData
l 可以触发观察的操作:create,delete,setData
Ø 写操作与zookeeper内部事件的对应关系
五个事件:
Ø zookeeper内部事件与watcher的对应关系
应该指的是不同的事件类型与调用exists(),getData(),getChildren()方法时,注册的Watcher之间的关系
Ø 写操作与watcher的对应关系
示例解读:
create(“/path”)会触发exists, getData中的Watcher中的process方法
Ø ACL
每个znode被创建时都会带有一个ACL列表,用于决定谁可以对它执行何种操作
身份验证模式有三种:
l digest:用户名,密码
l host:通过客户端的主机名来识别客户端
l ip: 通过客户端的ip来识别客户端
l new ACL(Perms.READ,newId("host","example.com"));
这个ACL对应的身份验证模式是host,符合该模式的身份是example.com,权限的组合是:READ
|
|
|
|
|
|
|
|
|
|
|
Ø Znode的节点状态
每个ACL都是身份验证模式、符合该模式的一个身份和一组权限的组合
Ø Zookeeper工作原理
l Zookeeper的核心是原子广播,这个机制保证了各个server之间的同步。实现这个机制的协议叫做Zab协议。Zab协议有两种模式,它们分别是恢复模式和广播模式。当服务启动或者在领导者崩溃后,Zab就进入了恢复模式,当领导者被选举出来,且大多数server的完成了和leader的状态同步以后,恢复模式就结束了。状态同步保证了leader和server具有相同的系统状态。
l 一旦leader已经和多数的follower进行了状态同步后,他就可以开始广播消息了,即进入广播状态。这时候当一个server加入zookeeper服务中,它会在恢复模式下启动,发现leader,并和leader进行状态同步。待到同步结束,它也参与消息广播。Zookeeper服务一直维持在Broadcast状态,直到leader崩溃了或者leader失去了大部分的followers支持。
l 广播模式需要保证proposal被按顺序处理,因此zk采用了递增的事务id号(zxid)来保证。所有的提议(proposal)都在被提出的时候加上了zxid。实现中zxid是一个64为的数字,它高32位是epoch用来标识leader关系是否改变,每次一个leader被选出来,它都会有一个新的epoch。低32位是个递增计数。
l 当leader崩溃或者leader失去大多数的follower,这时候zk进入恢复模式,恢复模式需要重新选举出一个新的leader,让所有的server都恢复到一个正确的状态。
Ø Leader选举
首先看一下选举的过程,zk的实现中用了基于paxos算法(主要是fastpaxos)的实现。具体如下;此外恢复模式下,如果是重新刚从崩溃状态恢复的或者刚启动的的server还会从磁盘快照中恢复数据和会话信息。(zk会记录事务日志并定期进行快照,方便在恢复时进行状态恢复)
l 每个Server启动以后都询问其它的Server它要投票给谁。
l 对于其他server的询问,server每次根据自己的状态都回复自己推荐的leader的id和上一次处理事务的zxid(系统启动时每个server都会推荐自己)
l 收到所有Server回复以后,就计算出zxid最大的哪个Server,并将这个Server相关信息设置成下一次要投票的Server。
l 计算这过程中获得票数最多的的sever为获胜者,如果获胜者的票数超过半数,则改server被选为leader。否则,继续这个过程,直到leader被选举出来。
l leader就会开始等待server连接
l Follower连接leader,将最大的zxid发送给leader
l Leader根据follower的zxid确定同步点
l 完成同步后通知follower 已经成为uptodate状态
l Follower收到uptodate消息后,又可以重新接受client的请求进行服务了
Observing: 观察状态,这时候observer会观察leader是否有改变,然后同步leader的状态;Following: 跟随状态,接收leader的proposal ,进行投票。并和leader进行状态同步
Looking: 寻找状态,这个状态不知道谁是leader,会发起leader选举;Leading: 领导状态,对Follower的投票进行决议,将状态和follower进行同步
Ø Zookeeper示例代码
输出的结果如下:
已经触发了 None 事件!
testRootData [testChildPathOne]
目录节点状态:[5,5,1281804532336,1281804532336,0,1,0,0,12,1,6]
已经触发了NodeChildrenChanged 事件!
testChildDataTwo
已经触发了NodeDeleted 事件!
已经触发了NodeDeleted 事件!
Ø 应用场景
l 应用场景1: 统一命名服务
n 分布式应用中,通常需要有一套完整的命名规则,既能够产生唯一的名称又便于人识别和记住,通常情况下用树形的名称结构是一个理想的选择,树形的名称结构是一个有层次的目录结构,既对人友好又不会重复。
n Name Service 是 Zookeeper 内置的功能,只要调用 Zookeeper 的 API 就能实现
l 应用场景2: 配置管理
n 配置的管理在分布式应用环境中很常见,例如同一个应用系统需要多台 PCServer 运行,但是它们运行的应用系统的某些配置项是相同的,如果要修改这些相同的配置项,那么就必须同时修改每台运行这个应用系统的 PC Server,这样非常麻烦而且容易出错。
n 将配置信息保存在 Zookeeper 的某个目录节点中,然后将所有需要修改的应用机器监控配置信息的状态,一旦配置信息发生变化,每台应用机器就会收到 Zookeeper 的通知,然后从Zookeeper 获取新的配置信息应用到系统中。
Zookeeper很容易实现这种集中式的配置管理,比如将APP1的所有配置配置到/APP1 znode下,APP1所有机器一启动就对/APP1这个节点进行监控(zk.exist(“/APP1″,true)),并且实现回调方法 Watcher,那么在zookeeper上/APP1 znode节点下数据发生变化的时候,每个机器都会收到通知,Watcher方法将会被执行,那么应用再取下数据即可 (zk.getData(“/APP1″,false,null));
l 应用场景3: 集群管理
n Zookeeper 能够很容易的实现集群管理的功能,如有多台 Server 组成一个服务集群,那么必须要一个“总管”知道当前集群中每台机器的服务状态,一旦有机器不能提供服务,集群中其它机器必须知道,从而做出调整重新分配服务策略。同样当增加集群的服务能力时,就会增加一台或多台 Server,同样也必须让“总管”知道。
n Zookeeper 不仅能够维护当前的集群中机器的服务状态,而且能够选出一个“总管”,让这个总管来管理集群,这就是 Zookeeper的另一个功能 Leader Election。
应用集群中,我们常常需要让每一个机器知道集群中(或依赖的其他某一个集群)哪些机器是活着的,并且在集群机器因为宕机,网络断链等原因能够不在人工介入的情况下迅速通知到每一个机器。Zookeeper同样很容易实现这个功能,比如我在zookeeper服务器端有一个znode叫/APP1SERVERS,那么集群中每一个机器启动 的时候都去这个节点下创建一个EPHEMERAL类型的节点,比如server1创建/APP1SERVERS/SERVER1(可以使用ip,保证不重 复),server2创建/APP1SERVERS/SERVER2,然后SERVER1和SERVER2都watch /APP1SERVERS这个父节点,那么也就是这个父节点下数据或者子节点变化都会通知 对该节点进行watch的 客户端。因为EPHEMERAL类型节 点有一个很重要的特性,就是客户端和服务器端连接断掉或者session过期就会使节点消失,那么在某一个机器挂掉或者断链的时候,其对应的节点就会消失,然后集群中所有对/APP1SERVERS进行watch的客户端都会收到通知,然后取得最新列表即可。
Zookeeper 如何实现 Leader Election,也就是选出一个 Master Server;另外有一个应用场景就是集群选master,一旦master挂掉能够马上能从slave中选出一个master,实现步骤和前者一样,只是机器在启动的 时候在APP1SERVERS创建的节点类型变为EPHEMERAL_SEQUENTIAL类型,这样每个节点会自动被编号
n zk.create("/testRootPath/testChildPath1","1".getBytes(),Ids.OPEN_ACL_UNSAFE,CreateMode.EPHEMERAL_SEQUENTIAL);
n zk.create(“/testRootPath/testChildPath2”,“2”.getBytes(), Ids.OPEN_ACL_UNSAFE,CreateMode.EPHEMERAL_SEQUENTIAL);
n zk.create("/testRootPath/testChildPath3","3".getBytes(),Ids.OPEN_ACL_UNSAFE,CreateMode.EPHEMERAL_SEQUENTIAL);
n zk.create("/testRootPath/testChildPath4","4".getBytes(),Ids.OPEN_ACL_UNSAFE,CreateMode.EPHEMERAL_SEQUENTIAL);
n System.out.println(zk.getChildren("/testRootPath",false));
n 打印结果:[testChildPath10000000000,testChildPath20000000001, testChildPath40000000003, testChildPath30000000002]
规定编号最小的为master,所以当我们对SERVERS节点做监控的时候,得到服务器列表,只要所有集群机器逻辑认为最小编号节点为master,那么master就被选出,而这个master宕机的时候,相应的znode会消失,然后新的服务器列表就被推送到客户端,然后每个节点逻辑认为最小编号节点为master,这样就做到动态master选举。
l 应用场景4:共享锁
共享锁在同一个进程中很容易实现,但是在跨进程或者在不同 Server 之间就不好实现了。Zookeeper 却很容易实现这个功能,实现方式也是需要获得锁的 Server 创建一个 EPHEMERAL_SEQUENTIAL 目录节点,然后调用 getChildren方法获取当前的目录节点列表中最小的目录节点是不是就是自己创建的目录节点,如果正是自己创建的,那么它就获得了这个锁,如果不是那么它就调用 exists(String path, boolean watch) 方法并监控 Zookeeper 上目录节点列表的变化,一直到自己创建的节点是列表中最小编号的目录节点,从而获得锁,释放锁很简单,只要删除前面它自己所创建的目录节点就行了。
l 应用场景5: 队列管理
n Zookeeper 可以处理两种类型的队列:当一个队列的成员都聚齐时,这个队列才可用,否则一直等待所有成员到达,这种是同步队列;队列按照 FIFO 方式进行入队和出队操作,例如实现生产者和消费者模型
n 创建一个父目录 /synchronizing,每个成员都监控目录 /synchronizing/start 是否存在,然后每个成员都加入这个队列(创建/synchronizing/member_i 的临时目录节点),然后每个成员获取 / synchronizing 目录的所有目录节点,判断 i 的值是否已经是成员的个数,如果小于成员个数等待 /synchronizing/start 的出现,如果已经相等就创建 /synchronizing/start。
Ø 总结:
l Zookeeper 作为 Hadoop 项目中的一个子项目,是 Hadoop 集群管理的一个必不可少的模块,它主要用来控制集群中的数据,如它管理 Hadoop 集群中的 NameNode,还有 Hbase 中 Master Election、Server 之间状态同步等。
l Zoopkeeper 提供了一套很好的分布式集群管理的机制,就是它这种基于层次型的目录树的数据结构,并对树中的节点进行有效管理,从而可以设计出多种多样的分布式的数据管理模型
2.Hadoop 的HA (****掌握***)
Ø 集群的概念
l 计算机集群是一种计算机系统, 它通过一组松散集成的计算机软件和/或硬件连接起来高度紧密地协作完成计算工作。
l 集群系统中的单个计算机通常称为节点,通常通过局域网连接。
l 集群技术的特点:
通过多台计算机完成同一个工作。达到更高的效率
两机或多机内容、工作过程等完全一样。如果一台死机,另一台可以起作用。
Ø linux机器准备工作(7台)
l 安装VMWare软件
详细安装文档见资料文件夹附件:虚拟机Vmware安装.doc
l 在VMWare软件下linux系统
详细安装文档见资料文件夹见附件:CentOS6详细安装文档.doc
l 配置VMWare虚拟软件网卡,保证Windows机器能和虚拟机linux正常通信
Ø 点击VMware快捷方式,右键打开文件所在位置 -> 双击vmnetcfg.exe -> VMnet1 host-only ->修改subnet ip 设置网段:192.168.0.0 子网掩码:255.255.255.0 -> apply ->ok
Ø 回到windows --> 打开网络和共享中心 -> 更改适配器设置 -> 右键VMnet1 -> 属性 -> 双击IPv4 -> 设置windows的IP:192.168.0.100 子网掩码:255.255.255.0 -> 点击确定
Ø 在虚拟软件上 --My Computer -> 选中虚拟机 -> 右键 -> settings -> networkadapter -> host only -> ok
l 修改主机名
vim/etc/sysconfig/network
NETWORKING=yes
HOSTNAME=zookeeperServer1 ###
l 设置linux机器IP
Ø 第一种:通过Linux图形界面进行修改(普通程序员专用)
进入Linux图形界面 -> 右键点击右上方的两个小电脑 -> 点击Edit connections -> 选中当前网络System eth0 -> 点击edit按钮 -> 选择IPv4 -> method选择为manual -> 点击add按钮 -> 添加IP:192.168.0.2 子网掩码:255.255.255.0 网关:192.168.0.1 -> apply
Ø 第二种:修改配置文件方式(屌丝程序员专用)
vim/etc/sysconfig/network-scripts/ifcfg-eth0
DEVICE="eth0"
BOOTPROTO="static" ###
HWADDR="00:0C:29:3C:BF:E7"
IPV6INIT="yes"
NM_CONTROLLED="yes"
ONBOOT="yes"
TYPE="Ethernet"
UUID="ce22eeca-ecde-4536-8cc2-ef0dc36d4a8c"
IPADDR="192.168.0.101" ###(注意:是每台机器对应的地址)
NETMASK="255.255.255.0" ###
GATEWAY="192.168.0.1" ###
l 修改主机名和IP的映射关系(注意:这里是7台机器对应的映射关系)
vim /etc/hosts
192.168.0.101 zookeeperServer1
192.168.0.102 zookeeperServer2
192.168.0.103 zookeeperServer3
192.168.0.104 nameNode1
192.168.0.105 nameNode2
192.168.0.106 resourceManager1
192.168.0.107 resourceManager2
l 关闭防火墙
#查看防火墙状态
service iptables status
#关闭防火墙
service iptables stop
#查看防火墙开机启动状态
chkconfig iptables --list
#关闭防火墙开机启动
chkconfig iptables off
l 重启系统
reboot
l 安装JDK
Ø 上传
Ø 解压jdk
#创建文件夹
mkdir /usr/java
#解压
tar -zxvf jdk-7u79-linux-i586.tar.gz -C/usr/java/
Ø 将java添加到环境变量中
vim /etc/profile
#在文件最后添加
JAVA_HOME=/usr/java/jdk1.7.0_79
export PATH=$JAVA_HOME/bin:$PATH
#刷新配置
source /etc/profile
Ø Hadoop集群搭建准备
机器名 |
机器IP |
用途 |
zookeeperServer1 |
192.168.0.101 |
Zookeeper/Journalnode/DataNode/NodeManager |
zookeeperServer2 |
192.168.0.102 |
Zookeeper/Journalnode/DataNode/NodeManager |
zookeeperServer3 |
192.168.0.103 |
Zookeeper/Journalnode/DataNode/NodeManager |
nameNode1 |
192.168.0.104 |
NameNode/zkfc |
nameNode2 |
192.168.0.105 |
NameNode/zkfc |
resourceManager1 |
192.168.0.106 |
ResourceManager |
resourceManager2 |
192.168.0.107 |
ResourceManager |
说明:
1.在hadoop2.0中通常由两个NameNode组成,一个处于active状态,另一个处于standby状态。Active NameNode对外提供服务,而Standby NameNode则不对外提供服务,仅同步active namenode的状态,以便能够在它失败时快速进行切换。
hadoop2.0官方提供了两种HDFS HA的解决方案,一种是NFS,另一种是QJM。这里我们使用简单的QJM。在该方案中,主备NameNode之间通过一组JournalNode同步元数据信息,一条数据只要成功写入多数JournalNode即认为写入成功。通常配置奇数个JournalNode这里还配置了一个zookeeper集群,用于ZKFC(DFSZKFailoverController)故障转移,当Active NameNode挂掉了,会自动切换Standby NameNode为standby状态
2.hadoop-2.2.0中依然存在一个问题,就是ResourceManager只有一个,存在单点故障,hadoop-2.4.1解决了这个问题,有两个ResourceManager,一个是Active,一个是Standby,状态由zookeeper进行协调.
Ø 搭建Hadoop集群详细步骤:
1.安装配置zooekeeper集群(在zookeeperServer1上)
1.1解压
tar-zxvf zookeeper-3.4.5.tar.gz -C /itcast/
1.2修改配置
cd/itcast/zookeeper-3.4.5/conf/
cpzoo_sample.cfg zoo.cfg
vimzoo.cfg
修改:dataDir=/itcast/zookeeper-3.4.5/tmp
在最后添加:
server.1=zookeeperServer1:2888:3888
server.2=zookeeperServer2:2888:3888
server.3=zookeeperServer3:2888:3888
保存退出
然后创建一个tmp文件夹
mkdir/itcast/zookeeper-3.4.5/tmp
再创建一个空文件
touch/itcast/zookeeper-3.4.5/tmp/myid
最后向该文件写入ID
echo 1 > /itcast/zookeeper-3.4.5/tmp/myid
1.3将配置好的zookeeper拷贝到其他节点(首先分别在zookeeperServer2、zookeeperServer3根目录下创建一个itcast/zookeeper-3.4.5目录:mkdir -p /itcast/zookeeper-3.4.5)
scp -r /itcast/zookeeper-3.4.5/* zookeeperServer2:/itcast/zookeeper-3.4.5/
scp-r /itcast/zookeeper-3.4.5/* zookeeperServer3:/itcast/zookeeper-3.4.5/
注意:修改zookeeperServer2、zookeeperServer3对应/itcast/zookeeper-3.4.5/tmp/myid的内容
zookeeperServer2:
echo 2 >/itcast/zookeeper-3.4.5/tmp/myid
zookeeperServer3:
echo 3 >/itcast/zookeeper-3.4.5/tmp/myid
2.安装配置hadoop集群(在nameNode1上操作)
2.1解压
tar-zxvf hadoop-2.4.1.tar.gz -C /itcast/
2.2配置HDFS(hadoop2.0所有的配置文件都在$HADOOP_HOME/etc/hadoop目录下)
#将hadoop添加到环境变量中
vim/etc/profile
exportJAVA_HOME=/usr/java/jdk1.7.0_79
exportHADOOP_HOME=/itcast/hadoop-2.4.1
exportPATH=$PATH:$JAVA_HOME/bin:$HADOOP_HOME/bin:$HADOOP_HOME/sbin
source /etc/profile
#hadoop2.0的配置文件全部在$HADOOP_HOME/etc/hadoop下
cd/itcast/hadoop-2.4.1/etc/hadoop
2.2.1修改hadoop-env.sh
export JAVA_HOME=/usr/java/jdk1.7.0_79
2.2.2修改core-site.xml
<configuration>
<!--指定hdfs的nameservice为ns1 -->
<property>
<name>fs.defaultFS</name>
<value>hdfs://ns1</value>
</property>
<!--指定hadoop临时目录 -->
<property>
<name>hadoop.tmp.dir</name>
<value>/itcast/hadoop-2.4.1/tmp</value>
</property>
<!--指定zookeeper地址 -->
<property>
<name>ha.zookeeper.quorum</name>
<value>zookeeperServer1:2181,zookeeperServer2:2181,zookeeperServer3:2181</value>
</property>
</configuration>
2.2.3修改hdfs-site.xml
<configuration>
<!--指定hdfs的nameservice为ns1,需要和core-site.xml中的保持一致-->
<property>
<name>dfs.nameservices</name>
<value>ns1</value>
</property>
<!--ns1下面有两个NameNode,分别是nn1,nn2 -->
<property>
<name>dfs.ha.namenodes.ns1</name>
<value>nn1,nn2</value>
</property>
<!-- nn1的RPC通信地址 -->
<property>
<name>dfs.namenode.rpc-address.ns1.nn1</name>
<value>nameNode1:9000</value>
</property>
<!--nn1的http通信地址-->
<property>
<name>dfs.namenode.http-address.ns1.nn1</name>
<value>nameNode1:50070</value>
</property>
<!--nn2的RPC通信地址 -->
<property>
<name>dfs.namenode.rpc-address.ns1.nn2</name>
<value>nameNode2:9000</value>
</property>
<!--nn2的http通信地址 -->
<property>
<name>dfs.namenode.http-address.ns1.nn2</name>
<value>nameNode2:50070</value>
</property>
<!--指定NameNode的元数据在JournalNode上的存放位置 -->
<property>
<name>dfs.namenode.shared.edits.dir</name>
<value>qjournal://zookeeperServer1:8485;zookeeperServer2:8485;zookeeperServer3:8485/ns1</value>
</property>
<!--指定JournalNode在本地磁盘存放数据的位置;此属性在官网hdfs中High Availability With QJM部分-->
<property>
<name>dfs.journalnode.edits.dir</name>
<value>/itcast/hadoop-2.4.1/journal</value>
</property>
<!--开启NameNode失败自动切换 -->
<property>
<name>dfs.ha.automatic-failover.enabled</name>
<value>true</value>
</property>
<!--配置失败自动切换实现方式;此属性在官网hdfs中High Availability With QJM部分 -->
<property>
<name>dfs.client.failover.proxy.provider.ns1</name>
<value>org.apache.hadoop.hdfs.server.namenode.ha.ConfiguredFailoverProxyProvider</value>
</property>
<!--配置隔离机制方法,多个机制用换行分割,即每个机制暂用一行-->
<property>
<name>dfs.ha.fencing.methods</name>
<value>
sshfence
shell(/bin/true)
</value>
</property>
<!--使用sshfence隔离机制时需要ssh免登陆 -->
<property>
<name>dfs.ha.fencing.ssh.private-key-files</name>
<value>/root/.ssh/id_rsa</value>
</property>
<!--配置sshfence隔离机制超时时间 -->
<property>
<name>dfs.ha.fencing.ssh.connect-timeout</name>
<value>30000</value>
</property>
</configuration>
2.2.4修改mapred-site.xml
<configuration>
<!--指定mr框架为yarn方式 -->
<property>
<name>mapreduce.framework.name</name>
<value>yarn</value>
</property>
</configuration>
2.2.5修改yarn-site.xml
<configuration>
<!-- 开启RM高可靠 -->
<property>
<name>yarn.resourcemanager.ha.enabled</name>
<value>true</value>
</property>
<!-- 指定RM的cluster id-->
<property>
<name>yarn.resourcemanager.cluster-id</name>
<value>yrc</value>
</property>
<!-- 指定RM的名字 -->
<property>
<name>yarn.resourcemanager.ha.rm-ids</name>
<value>rm1,rm2</value>
</property>
<!-- 分别指定RM的地址 -->
<property>
<name>yarn.resourcemanager.hostname.rm1</name>
<value>resourceManager1</value>
</property>
<property>
<name>yarn.resourcemanager.hostname.rm2</name>
<value>resourceManager2</value>
</property>
<!-- 指定zk集群地址 -->
<property>
<name>yarn.resourcemanager.zk-address</name>
<value>zookeeperServer1:2181,zookeeperServer2:2181,zookeeperServer3:2181</value>
</property>
<property>
<name>yarn.nodemanager.aux-services</name>
<value>mapreduce_shuffle</value>
</property>
</configuration>
2.2.6修改slaves(slaves是指定子节点的位置,因为要在nameNode1上启动HDFS、在resourceManager1启动yarn,所以nameNode1上的slaves文件指定的是datanode的位置,resourceManager1上的slaves文件指定的是nodemanager的位置)
zookeeperServer1
zookeeperServer2
zookeeperServer3
2.2.7配置免密码登陆
#首先要配置nameNode1到nameNode2、resourceManager1、resourceManager2、zookeeperServer1、zookeeperServer2、zookeeperServer3的免密码登陆
#在nameNode1上生产一对钥匙
ssh-keygen -t rsa
#将公钥拷贝到其他节点,包括自己
ssh-copy-id nameNode1
ssh-copy-id nameNode2
ssh-copy-id resourceManager1
ssh-copy-id resourceManager2
ssh-copy-id zookeeperServer1
ssh-copy-id zookeeperServer2
ssh-copy-id zookeeperServer3
#配置resourceManager1到resourceManager2、zookeeperServer1、zookeeperServer2、zookeeperServer3的免密码登陆
#在resourceManager1上生产一对钥匙
ssh-keygen -t rsa
#将公钥拷贝到其他节点
ssh-copy-id resourceManager2
ssh-copy-id zookeeperServer1
ssh-copy-id zookeeperServer2
ssh-copy-id zookeeperServer3
#注意:两个namenode之间要配置ssh免密码登陆,别忘了配置nameNode2到nameNode1的免登陆
在nameNode2上生产一对钥匙
ssh-keygen -t rsa
ssh-copy-id nameNode1
2.4将配置好的hadoop拷贝到其他节点
scp-r /itcast/ nameNode2:/
scp-r /itcast/ resourceManager1:/
scp-r /itcast/ resourceManager2:/
scp-r /itcast/ zookeeperServer1:/
scp-r /itcast/ zookeeperServer2:/
scp-r /itcast/ zookeeperServer3:/
Ø 启动与初始化hadoop集群
###注意:严格按照下面的步骤先检查各台hadoop环境变量是否设置好
2.5启动zookeeper集群(分别在zookeeperServer1、zookeeperServer2、resourceManager2上启动zk)
cd/itcast/zookeeper-3.4.5/bin/
./zkServer.shstart
#查看状态:一个leader,两个follower
./zkServer.shstatus
2.6启动journalnode(分别在在zookeeperServer1、zookeeperServer2、zookeeperServer3上执行)
cd/itcast/hadoop-2.4.1
sbin/hadoop-daemon.shstart journalnode
#运行jps命令检验,zookeeperServer1、zookeeperServer2、zookeeperServer3上多了JournalNode进程
2.7格式化HDFS
#在nameNode1上执行命令:
hdfsnamenode -format
#格式化后会在根据core-site.xml中的hadoop.tmp.dir配置生成个文件,这里我配置的是/itcast/hadoop-2.4.1/tmp,然后将/itcast/hadoop-2.4.1/tmp拷贝到nameNode2的/itcast/hadoop-2.4.1/下。
scp-r /itcast/hadoop-2.4.1/tmp/ nameNode2:/itcast/hadoop-2.4.1/
2.8格式化ZK(在nameNode1上执行即可)
hdfs zkfc -formatZK
2.9启动HDFS(在nameNode1上执行)
sbin/start-dfs.sh
2.10启动YARN(#####注意#####:是在resourceManager1上执行start-yarn.sh,把namenode和resourcemanager分开是因为性能问题,因为他们都要占用大量资源,所以把他们分开了,他们分开了就要分别在不同的机器上启动)
sbin/start-yarn.sh
Ø 验证集群是否可用
启动完成后,可以统计浏览器访问:
http://192.168.0.104:50070
NameNode 'nameNode1:9000' (active)
http://192.168.0.105:50070
NameNode 'nameNode2:9000' (standby)
验证HDFS HA
Ydh:测试,在stanby的namenode上上传一个文件,会有什么现象?
首先向hdfs上传一个文件
hadoop fs -put /etc/profile /profile
hadoop fs -ls /
然后再kill掉active的NameNode
kill -9 <pid of NN>
通过浏览器访问:http://192.168.0.202:50070
NameNode 'nameNode2:9000' (active)
这个时候nameNode2上的NameNode变成了active
在执行命令:
hadoop fs -ls /
-rw-r--r-- 3 root supergroup 1926 2014-02-06 15:36 /profile
刚才上传的文件依然存在!!!
手动启动那个挂掉的NameNode
sbin/hadoop-daemon.sh start namenode
通过浏览器访问:http://192.168.0.105:50070
NameNode 'nameNode1:9000' (standby)
验证YARN:
运行一下hadoop提供的demo中的WordCount程序:
hadoop jarshare/hadoop/mapreduce/hadoop-mapreduce-examples-2.4.1.jar wordcount/profile/out
Ø 一些启动命令:(***记住***)
启动namenode
hadoop-daemon.sh start namenode
启动datanode
hadoop-daemon.sh start datanode
启动journalnode
hadoop-daemon.sh start journalnode
启动zookeeper
./zkServer.sh start
启动hdfs
start-dfs.sh
启动yarn
start-yarn.sh