使用NFS实现HA(HDFS High Availability With NFS)

目的

本指南概述HDFS的高可用性(HA)的特性,以及如何配置和管理HA HDFS集群,使用NFS实现NameNode共享存储
本文假设读者有一个大致了解通用组件和一个HDFS集群中的节点类型。详情请参阅HDFS架构指南。

注意:QJM或者共享存储

本指南讨论如何配置使用HDFS HA使用NFS目录在活跃的和备份的NameNode之间分享edit日志,对于如何通过QJM实现HA请参考上篇博客。

背景

Hadoop 2.0.0之前,NameNode是在一个HDFS集群一个单点故障(SPOF)。每个集群有一个NameNode,如果那台机器坏掉,集群作为一个整体将不可用,直到NameNode启动或在另一个单独的机器上配置的。
这种设计将影响HDFS集群的可用性在两个主要方面:
计划外的事件,如NameNode宕机导致集群不可用。
计划内的维护活动,比如NameNode机器上的软件或硬件升级导致集群停机。
HDFS高可用性特性解决了上面的问题,可以通过在同一集群上配置运行两个冗余的NameNodes,做到主动/被动的热备份。这将允许当一个机器宕机时,快速转移到一个新的NameNode,或管理员进行利用故障转移达到优雅的系统升级的目的。

架构

一个典型的HA集群,NameNode会被配置在两台独立的机器上.在任何的时间上,一个NameNode处于活动状态,而另一个在备份状态,活动状态的NameNode会响应集群中所有的客户端,同时备份的只是作为一个副本,保证在必要的时候提供一个快速的转移。

为了备份节点和活跃的节点状态同步,当前的实现要求两个节点可以连接到一个共享设备上的目录(例如网络存储的网络文件系统)。这个架构会在以后的版本中实现。

当任何的namespace被活动状态的节点修改,他会记录在共享文件夹的edit日志文件中。备份节点观察共享文件夹的edit,他允许拥有自己的namespace。在执行自动迁移之前,备份节点在转换为活动的节点之前确认已经读取到共享存储当中所有的edit。这将确保和迁移之前完全同步。

为了提供一个快速的转移,备份NameNode要求保存着最新的block在集群当中的信息。为了能够得到这个,DataNode都被配置了所有的NameNode的地址,并且发送block的地址信息和心跳给两个node。

保证只有一个活跃的NameNode在集群当中是一个十分重要的一步。否则namespace状态在两个节点间不同会导致数据都是或者其他一些不正确的结果。为了确保这个,防止所谓split - brain场景,管理员至少为共享存储配置一个过滤方法。故障转移期间,如果前一个活跃节点不再是活跃状态那么他将无法通过过滤,过滤过程负责切断前一活跃的节点写入共享存储edits的权限。这会有效防止其他NameNode持续处于活跃状态,允许新的活动节点安全进行故障转移。

硬件资源

为了部署一个HA集群,你应该按照以下准备:


NameNode机器:机器负责运行活动和和备份的NameNode,两台机器应该有着完全一样的硬件,同样的硬件应该和没有HA的硬件完全一致。


共享存储:需要有一个共享文件夹并且所有的NameNode机器都有读写权限。通常这是一个远程文件,支持NFS并安装挂载在每个NameNode机器。目前只有单一的共享edits文件夹被支持。因此,系统的可用性被共享的edits文件夹所限制,为了解决这个单点则需要edits文件夹的冗余。具体来说,多个网络的存储路径和冗余存储本身(磁盘、网络、和权力)。因为这个原因,建议共享存储服务器是一个高质量的专用NAS设备而不是一个简单的Linux服务器。
注意:在一个HA集群中备份的NameNode也要坚持namespace的状态,那么就没有必要去运行一个Secondary NameNode, CheckpointNode, 或者是BackupNode在集群当中,事实上这么做的话有可能会是一个错误。为了允许有一个重新配置的非HA的集群可以实现HA,并且实现硬件的重用,所以把以前的secondary NameNode的机器作为这样一个机器。

部署


配置综述

HA的配置向后兼容允许既存的单NameNode配置在没有任何改动的情况下工作,新的配置被设计成集群当中的所有节点拥有着相同的配置并且并不需要为不同的机器设置不同的配置文件。

如HDFS Federation,HA集群重用nameserviceID去标示一个HDFS实例这个实例可能实际上包含了很多的HA NameNodes。另外一个新的抽象叫做NameNode ID被添置到了HA。在集群中每个不同的NameNode有着不同的NameNode ID 去标示他,所有的NameNode采用同一个配置文件,相关的配置参数都被用nameservice ID和NameNode ID作为后缀。

配置细节

配置HA NameNodes,你必须添加几个配置选项到你的hdfs-site.xml配置文件当中。
这是这些配置的顺序并不重要,但是你为dfs.nameservices和dfs.ha.namenodes.[nameservice ID] 设置的值将要决定下面步骤的key,因此,你应该决定这些值在设置这些选项之前。
dfs.nameservices -新的nameservice的逻辑名字
为nameservice选择一个名字,例如“mycluster”,并且用这个名字的值来作为一些配置项的值,这个名字是任意的。他将被用来配置在集群中作为HDFS的绝对路径组件。
注意如果你也采用HDFS系统,这个设置应该也包括一个包含其他nameservices,HA或者一个逗号分隔的列表
<property>
  <name>dfs.nameservices</name>
  <value>mycluster</value>
</property>

dfs.ha.namenodes.[nameservice ID] -为在nameservice中的每一个NameNode设置唯一标示符。

配置一个逗号分隔的 NameNode ID列表。这将是被DataNode识别为所有的NameNode。例如,如果使用“mycluster”作为nameservice ID,并且使用“nn1”和“nn2”作为NameNodes标示符,你应该如下配置:
<property>
  <name>dfs.ha.namenodes.mycluster</name>
  <value>nn1,nn2</value>
</property>
注意:在每一个nameservice中最多只能有两个NameNode可以被配置

dfs.namenode.rpc-address.[nameservice ID].[name node ID] - 每个NameNode监听的完整正确的RPC地址
对于先前配置的NameNode ID,设置全地址和IP端口的NameNode进程,注意配置两个独立的配置选项例如:
<property>
<name>dfs.namenode.rpc-address.mycluster.nn1</name>
<value>machine1.example.com:8020</value>
</property>
<property>
<name>dfs.namenode.rpc-address.mycluster.nn2</name>
<value>machine2.example.com:8020</value>
</property>
注意:如果您愿意,您可能同样配置“servicerpc-address”设置
dfs.namenode.http-address.[nameservice ID].[name node ID] -每个NameNode监听的完整正确的HTTP地址
和上面设置rpc-address一样,设置NameNode的HTTP服务,例如:
<property>
<name>dfs.namenode.http-address.mycluster.nn1</name>
<value>machine1.example.com:50070</value>
</property>
<property>
<name>dfs.namenode.http-address.mycluster.nn2</name>
<value>machine2.example.com:50070</value>
</property>
注意:如果Hadoop的安全特征被开启,你应该类似的设置https-address为每一个NameNode

dfs.namenode.shared.edits.dir - 共享存储文件夹的地址。

这里配置一个edits的远程共享目录,该目录用于备份节点获取所有活跃节点造成的文件系统的更新,你应该配置只配置一个这样的目录。这个目录应该可以被所有的NameNode读写,这个应该是一个绝对路径,例如:

<property>
  <name>dfs.namenode.shared.edits.dir</name>
  <value>file:///mnt/filer1/dfs/ha-name-dir-shared</value>
</property>

dfs.client.failover.proxy.provider.[nameservice ID] -HDFS客户端使用的Java类与活跃的NameNode联系
配置一个类的名字用来被DFS客户端确定那个NameNode是目前活跃的那个NameNode现在正在提供响应。目前唯一的实现是已经附带的ConfiguredFailoverProxyProvider,除非自己实现一个,例如:
<property>
<name>dfs.client.failover.proxy.provider.mycluster</name>
<value>org.apache.hadoop.hdfs.server.namenode.ha.ConfiguredFailoverProxyProvider</value>
</property>

dfs.ha.fencing.methods - 在故障转移的期间,一个脚本或者java类的列表用来筛选活动NameNode。

在任何时间只有一个活动的NameNode 都是系统所需的。我们需要确认活跃的NameNode转换为备份的状态,或者防止在其他NameNode转换为活跃状态之前,进程被终结。为了这个目的我们需要配置至少一个过滤方法(fencing method)。

过滤方法被配置为carriage-return-separated列表会在故障转移的时候被调用,直到一个过滤返回success。有两个方法比Hadoop使用: 
shell和sshfence。如果想自定义可以看theorg.apache.hadoop.ha.NodeFencer类。

sshfence -利用SSH连接到NameNode服务器并杀死进程
sshfence选项SSH连接到目标节点,并使用fuser杀死进程。为了这个过滤选项可以工作,他需要通过通过SSH的无秘钥登陆到目标节点,那么需要配置一个dfs.ha.fencing.ssh.private-key-files选项,他以逗号分隔,提供SSH的key文件比如:
<property> <name>dfs.ha.fencing.methods</name> <value>sshfence</value> </property> <property> <name>dfs.ha.fencing.ssh.private-key-files</name> <value>/home/exampleuser/.ssh/id_rsa</value> </property>
可以通过不标准username或者port来实现SSH,我们也可以配置一个超时时间(毫秒),如果这个时间没有连接上那么会返回一个失败。例如:
<property> <name>dfs.ha.fencing.methods</name> <value>sshfence([[username][:port]])</value> </property> <property> <name>dfs.ha.fencing.ssh.connect-timeout</name> <value>30000</value> </property>
shell - 运行任何的shell命令去过滤活动的NameNode
shell过滤方法运行任何的shell命令,他可以被配置例如:
<property> <name>dfs.ha.fencing.methods</name> <value>shell(/path/to/my/script.sh arg1 arg2 ...)</value> </property>
括号之间的字符串会被直接传递给shell脚本并且不要有任何的闭括号。

这个脚本将会带着环境建立时候所有的hadoop配置变量运行,在配置的key的变量中的‘_’会被替换成'.'这种方式已经被使用在NameNode的配置中如dfs_namenode_rpc-address 是为了涵盖目标节点的RPC地址,配置dfs.namenode.rpc-address.ns1.nn1也可以指定变量
另外,以下变量也可以使用
$target_host hostname of the node to be fenced
$target_port IPC port of the node to be fenced
$target_address the above two, combined as host:port
$target_nameserviceid the nameservice ID of the NN to be fenced
$target_namenodeid the namenode ID of the NN to be fenced
这些环境变量也可以用来替换shell命令,例如
<property> <name>dfs.ha.fencing.methods</name> <value>shell(/path/to/my/script.sh --nameservice=$target_nameserviceid $target_host:$target_port)</value> </property>
如果返回0,过滤方法并认为是成功,其他则认为不成功会调用下一个过滤方法。
注意:这个方式不能实现超时功能,如果想实现,应该通过shell脚本自己实现(比如,通过子分支强制杀死其母分支在一定的时间后)。
fs.defaultFS - 当什么都没有给定的时候Hadoop文件系统客户端默认的路径前缀
可选项,你可以配置一个默认的hadoop客户端路径作为新的HA的逻辑URI。如果你用“mycluster”作为 nameservice ID。这个值将作为你的HDFS路径的部分。可以通过core-site.xml文件进行如下配置。
<property> <name>fs.defaultFS</name> <value>hdfs://mycluster</value> </property>

部署细节

在完成必要的配置之后,必须进行一次初始化同步在两个HA的NameNode,主要是为了元数据。
如果你建立一个新的HDFS集群你应该首先运行一下format命令(hdfs namenode -format)在其中一个NameNode上。
如果你已经进行过Format NameNode,或者是正在将一个非HA的集群转换为一个HA的集群,你应该拷贝你的NameNode上的元数据文件夹的内容到另一个没有被格式化的NameNode,运行”hdfs namenode -bootstrapStandby“在没有格式化的NameNode上。
如果你讲一个不是HA的集群转换为一个HA的集群,你应该运行”hdfs -initializeSharedEdits“命令,这个会初始化edits共享文件夹使用本地NameNode的edits的文件夹中的edits数据

这是你需要启动两个HA的NameNode作为你日常的NameNode启动。

你能访问每一个NameNode的web页面通过配置的HTTP地址,你应该注意到在配置的地址旁边就是HA的状态(‘active’或者‘standby’)什么时候一个HA NameNode 启动它会被初始化为备份状态。

管理命令
现在HA的NameNode被配置并且启动了,你将有权限去利用命令管理你的HA HDFS集群,你应该熟悉你的所有的”hdfs haadmin“命令。运行这个命令没有任何的参数你会看见一下内容:
Usage: DFSHAAdmin [-ns <nameserviceId>] [-transitionToActive <serviceId>] [-transitionToStandby <serviceId>] [-failover [--forcefence] [--forceactive] <serviceId> <serviceId>] [-getServiceState <serviceId>] [-checkHealth <serviceId>] [-help <command>]
这个描述了常用的命令,每个子命令的详细信息你应该运行”hdfs haadmin -help <command>
transitionToActive and transitionToStandby - 切换NameNode的状态(Active或者Standby)
这些子命令会使NameNode分别转换状态,这种方式不会去调用人任何的过滤所以很少会被使用,想法人们应该选择“hdfs haadmin -failover”子命令。
failover - 启动两个NameNode之间的故障迁移
这个子命令会从第一个NameNode迁移到第二个,如果第一个NameNode处于备用状态,这个命令只没有错误的转换第二个节点到活动状态。如果第一个NameNode处于活跃状态,试图将优雅地转换到备用状态。如果失败,过滤方法(如由dfs.ha.fencing.methods配置)将尝试过滤直到成功。只有在这个过程之后第二个NameNode会转换为活动状态,如果没有过滤方法成功,第二个nameNode将不会活动并返回一个错误
getServiceState -判定NameNode的状态
连接到NameNode,去判断现在的状态打印“standby”或者“active”去标准的输出。这个子命令可以被corn jobs或者是监控脚本使用,为了针对不同专题的NameNode采用不同的行为
checkHealth -检查NameNode的健康
连接NameNode检查健康,NameNode能够执行一些诊断,包括检查如果内部服务正在运行。如果返回0表明NameNode健康,否则返回非0.可以使用此命令用于监测目的。
注意:这个功能实现的不完整,目前除了NameNode完全的关闭,其他全部返回成功。


自动迁移


介绍

上面的小节介绍的如何手动的配置迁移,在那种末实现即使活动的节点已经失败了,系统也不会自动的迁移到备用的节点,这个小节描述如何自动的配置和部署故障转移

组件

自动的故障转移添加了两周新的组件到HDFS部署中:一个是ZooKeeper quorum一个是the ZKFailoverController process(缩写是ZKFC)。
Apache ZooKeeper是一个通过少量的协作的数据,通知客户端的变化,并且监控客户端失败的高可用协调系统。实现HDFS的自动故障转移需要ZooKeeper做下面的事情:
失败保护-集群当中每一个NameNode机器都会在ZooKeeper维护一个持久的session,如果机器宕机,那么就会session过期,故障迁移会被触发。
活动的NameNode选择-ZooKeeper提供了一个简单的机制专门用来选择一个活跃的节点。如果现在的活跃的NameNode宕机其他的节点可以向ZooKeeper申请排他所成为下一个active的节点。
ZKFailoverController (ZKFC)是一个新的组件他是一个ZooKeeper的客户端也是用来监控和管理NameNode的状态的。每一个机器运行一个NameNode同时也要运行一个ZKFC,ZKFC是为了:
健康监控-ZKFC周期性的连接本地的NameNode运行一个健康检查命令,只要NameNode予以相应则ZKFC认为是健康的,如果节点宕机,冻结或者进入一个不健康的状态,那么健康监控器就会标示他是不健康的
ZooKeeper session管理-当本地NameNode是健康的时候,ZKFC会在ZooKeeper中保持一个开着的session。如果本地的NameNode是活跃的,他也会保持一个特殊的所在znode当中,这个锁用来使得ZooKeeper支持"ephemeral"节点,如果session超期那么这个锁会被删除。
ZooKeeper-based选择 - 如果本地的NameNode是健康的,ZKFC没有发现其他节点去持有锁那么他会申请锁。如果他成功了,它已经赢得了选举,并负责运行故障转移使其本地NameNode活跃。迁移过程和手动迁移类似:首先执行必要的过滤,然后将本地的NameNode转换为活动的,
更多的细节请查看自动迁移的设计HADOOP的JIRA的HDFS-2185.
部署ZooKeeper
一个部署中,ZooKeeper的守护线程被配置到3或者5个节点,因为ZooKeeper占用的资源比较轻量级,他可以和HDFS的NameNode和备份Node部署在同一硬件环境上。很多运行商部署选择部署第三个ZooKeeper进程和YARN的RM在同一个节点上,建议配置ZooKeeper节点去储存他们的数据在HDFS元数据分离的硬盘上为了更好地性能。
ZooKeeper 的安装不包括在本文档中,我们假设你已经建立了ZooKeeper集群运行了3个或3个以上的节点并且验证他可以被ZK CLI连接并且正确的操作。
开始之前
在你开始配置自动转移之前,你应该关闭你的集群,目前不能在集群运行当中实现手动到自动的转换
配置
配置自动故障转移要求添加两个新的配置到hdfs-site.xml,如下:
 <property> <name>dfs.ha.automatic-failover.enabled</name> <value>true</value> </property>
这个配置需要添加到core-site.xml文件中,如下:
 <property> <name>ha.zookeeper.quorum</name> <value>zk1.example.com:2181,zk2.example.com:2181,zk3.example.com:2181</value> </property>

这是一个主机端口的匹配在ZooKeeper 服务中。
如先前的文档中关于参数的描述,这些设置可能需要被配置先前的nameservice并用nameservice ID作为后缀,比如在集群中,你可能期望自动故障转移只是发生在一个nameservice上那么可以设置dfs.ha.automatic-failover.enabled.my-nameservice-id.

还有一些参数也可以设置并且对于自动迁移或一些影响,但是他们对于绝大多数的安装来说不是必要的。详细内容请参考配置主键key文档。

ZooKeeper初始化HA状态

在配置的主键被添加之后,下一步就是在ZooKeeper中初始化需要的状态,你可以在一个NameNode的主机上运行下面的命令:

$ hdfs zkfc -formatZK
他会在ZooKeeper 创建一个Znode代替用来为自动迁移储存数据。

使用start-dfs.sh启动集群

因为自动迁移被配置在文件中,start-dfs.sh脚本会自动启动一个ZKFC守护线程在NameNode运行的机器上,当ZKFC启动时,他会自动选择一个NameNode作为活动的。

手动启动集群

如果你手动管理你的集群中的服务,你需要手动的为每一个NameNode的机器去启动zkfc,你可以运行下面的命令:

$ hadoop-daemon.sh start zkfc
安全的进入ZooKeeper

如果你运行的是一个安全的集群,你会希望在ZooKeeper储存的信息也是安全的这会防止恶意的客户端改变ZooKeeper的元数据或者触发错误的故障转移。

为了实现安全的信息,首先需要在core-site.xml添加下面的内容:

 <property> <name>ha.zookeeper.auth</name> <value>@/path/to/zk-auth.txt</value> </property> <property> <name>ha.zookeeper.acl</name> <value>@/path/to/zk-acl.txt</value> </property>
请注意‘@’字符这个配置不是指向内部,而是指向磁盘上的文件。
第一个配置指定了ZooKeeper证书文件列表,和ZK CLI使用相同的格式,例如你可以这样声明:
digest:hdfs-zkfcs:mypassword
--hdfs-zkfcs是一个ZooKeeper用户名,mypassword是一个密码
ZooKeeper ACL验证这个证书:
$ java -cp $ZK_HOME/lib/*:$ZK_HOME/zookeeper-3.4.2.jar org.apache.zookeeper.server.auth.DigestAuthenticationProvider hdfs-zkfcs:mypassword
output: hdfs-zkfcs:mypassword->hdfs-zkfcs:P/OQvnYyU/nF/mGYvB/xurX8dYs=
复制粘贴->后面的字符串到zk-acls.tx,“digest:”作为前缀,比如:
digest:hdfs-zkfcs:vlUvLnd8MlacsE80rDuu6ONESbM=:rwcda
为了这些ACL起作用,你应该运行zkfc -format命令如上描述。
这样做之后,你可以验证的acl ZK CLI如下:
[zk: localhost:2181(CONNECTED) 1] getAcl /hadoop-ha
'digest,'hdfs-zkfcs:vlUvLnd8MlacsE80rDuu6ONESbM=
: cdrwa
验证自动迁移
一旦自动迁移被建立,你应该测试一下他。这么做,首先定位活跃的NameNode,你可以通过访问NameNode的web页面查看哪个node是活跃的在首页上你能看见HA的状态。
一旦你找到活跃的NameNode,你可以在这个节点上造一些错误。例如,你可能使用kill -9 <NN的进程>模拟JVM崩溃。或者重启机器拔掉网线模拟各种的异常。触发中断后,你希望几秒后其他的NameNode自动的编程活动的。自动转移的时间你可以通过一个配置ha.zookeeper.session-timeout.ms来设定,默认是5秒。

如果这个测试没有成功,你可能是一些地方配置错了,你需要检查zkfc守护进程的日志以及NameNode守护进程进一步诊断问题。



自动迁移FAQ

    • 开始ZKFC和NameNode守护进程的启动顺序很重要吗?
    不,任何定节点上你可能会在启动ZKFC之前或之后启动相应的NameNode。
    • 额外的监控应该放到什么地方?
    你应该为每一个NameNode的主机添加一个监控确定ZKFC运行。如果ZooKeeper失败,比如,ZKFC意外退出,应该重新启动,确保系统自动故障转移。
    此外,你应该监控ZooKeeper quorum的每一个服务器,如果ZooKeeper关闭了,那么自动迁移不能工作
    • 如果ZooKeeper关闭了怎么办?
    如果ZooKeeper 机器崩溃,自动迁移将不会在工作,但是HDFS不会有影响。当ZooKeeper 重新启动,HDFS会重新连上。
    • 我可以指定NameNode的优先级吗?
    不。目前这个不被支持。
    • 当自动转移被配置如何进行手工转移?
    即使配置了自动转移,你也可以使用手动转移

BookKeeper作为共享存储(扩展)

BookKeeper是NameNode共享存储的一个选择。BookKeeper通过早多个高性能存储节点之间复制edit的日志实现了一个高可用。edit的日志可以通过高性能的节点实现高性能。过滤方法也可以被支持,例如BookKeeper 不允许同时有两个对象可以写入同一个edit日志。

BookKeeper的元数据被储存在ZooKeeper中。在HA架构中,ZKFC需要Zookeeper集群支持,这个集群同样也为BookKeeper元数据服务。

更多的细节可以参考BookKeeper文档。

BookKeeperJournalManager 是一个HDFS JournalManager的实现接口,运行用户自定义实现日志写入HDFS的NameNode当中.

BookKeeper Journal Manager

使用BookKeeperJournalManager应该添加下面的内容到hdfs-site.xml

  <property>
      <name>dfs.namenode.shared.edits.dir</name>
      <value>bookkeeper://zk1:2181;zk2:2181;zk3:2181/hdfsjournal</value>
    </property>

    <property>
      <name>dfs.namenode.edits.journal-plugin.bookkeeper</name>
      <value>org.apache.hadoop.contrib.bkjournal.BookKeeperJournalManager</value>
    </property>
bookkeeper 的URI形式是bookkeeper://[zkEnsemble]/[rootZnode] [zookkeeper ensemble] 是一个分号分隔的列表,与zookeeper 的host:port 匹配。例如上面是3个服务zk1, zk2 & zk3,每一个都是监听2181端口。

[root znode]是zookeeper的znode的路径用来储存edit日志信息

必须在NameNode的类路径下为ournal-plugin指定类。会解释如何使用journal manager生成一个jar文件,并把它引入classpath下。

更多的配置选项.

dfs.namenode.bookkeeperjournal.output-buffer-size - bookkeeper journal流缓冲的字节数。默认是1024

    <property>
         <name>dfs.namenode.bookkeeperjournal.output-buffer-size</name>
         <value>1024</value>
       </property>
dfs.namenode.bookkeeperjournal.ensemble-size - bookkeeper服务在edit日志的数量,这个数量是可以写入edit日志的服务的数量,默认是3

   <property>
         <name>dfs.namenode.bookkeeperjournal.ensemble-size</name>
         <value>3</value>
       </property>

dfs.namenode.bookkeeperjournal.quorum-size - bookkeeper 可以写入的数量。这个数量用来认定写入。默认是2

    <property>
         <name>dfs.namenode.bookkeeperjournal.quorum-size</name>
         <value>2</value>
       </property>
dfs.namenode.bookkeeperjournal.digestPw - 当创建edit日志段的时候需要的密码

    <property>
        <name>dfs.namenode.bookkeeperjournal.digestPw</name>
        <value>myPassword</value>
       </property>
dfs.namenode.bookkeeperjournal.zk.session.timeout - Zookeeper 客户端从BookKeeper Journal Manager的session超时时间。Hadoop要求这个值应该小于ZKFC 的session超时时间默认为3000

      <property>
         <name>dfs.namenode.bookkeeperjournal.zk.session.timeout</name>
         <value>3000</value>
       </property>
构建BookKeeper Journal Manager plugin jar

为BK journal生成一个分布的包应该这么做:

$ mvn clean package -Pdist

这会生成一个BookKeeperJournalManager的jar,all the dependencies needed by the journal manager, hadoop-hdfs/src/contrib/bkjournal/target/hadoop-hdfs-bkjournal-VERSION.jar

注意:-Pdist的部分很重要,否则将无法形成一个jar的包。这个依赖包含进jar路径避免与其他的NameNode依赖冲突

放置BookKeeperJournalManager到NameNode classpath

运行一个HDFSNameNode并使用BookKeeper,需要拷贝bkjournal jar到hdfs的lib目录。在HDFS的文件系统中,他应该是

$HADOOP_HDFS_HOME/share/hadoop/hdfs/lib/

当前的限制

1)NameNode格式自动命令不会格式化BookKeeper数据。我们不得不手动清空BookKeeper集群数据,在Zookeeper创建/ledgers/available路径

---- $ zkCli.sh create /ledgers 0 $ zkCli.sh 创建 /ledgers/available 0

注意:bookkeeper://zk1:2181;zk2:2181;zk3:2181/hdfsjournal最后部分的/hdfsjournal指明在zookeeper的znode,储存元数据的储存路径,管理员可以设置喜欢的值。

2)BookKeeper不支持SASL和SSL连接

3)自动恢复存储节点的失败。只能参考下面的文章(BOOKKEEPER-237),手动恢复数据。


你可能感兴趣的:(使用NFS实现HA(HDFS High Availability With NFS))