ZooKeeper在HBase中的应用

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了ZooKeeper在HBase中的应用相关的知识,希望对你有一定的参考价值。

参考技术A ZooKeeper是一个开源的分布式协调服务,由雅虎创建,是Google Chubby的开源实现。分布式应用程序可以基于ZooKeeper实现诸如数据发布/订阅、负载均衡、命名服务、分布式协调/通知、集群管理、Master选举、分布式锁和分布式队列等功能。

既然ZooKeeper的作用这么大,那我们就来详细说说ZooKeeper在HBase中的应用叭!

一个分布式HBase系统安装依赖于一个运行着的ZooKeeper集群,所有参与的节点和客户端必须能够正常访问运行着的ZooKeeper集群。HBase默认为你提供一个节点的ZooKeeper集群,它会伴随着HBase start/stop进程的启动/停止而启动/停止。那么HBase主要用ZooKeeper来干什么呢?HBase主要用ZooKeeper来实现HMaster选举与主备切换、系统容错、RootRegion管理、Region状态管理和分布式SplitWAL任务管理等。

一,HMaster选举与主备切换

HMaster选举与主备切换的原理和HDFS中NameNode及YARN中ResourceManager的HA原理相同。

二,系统容错

当HBase启动时,每个RegionServer都会到ZooKeeper的/hbase/rs节点下创建一个信息节点(下文中,我们称该节点为”rs状态节点”),例如/hbase/rs/[Hostname],同时,HMaster会对这个节点注册监听。当某个 RegionServer 挂掉的时候,ZooKeeper会因为在一段时间内无法接受其心跳(即 Session 失效),而删除掉该 RegionServer 服务器对应的 rs 状态节点。与此同时,HMaster 则会接收到 ZooKeeper 的 NodeDelete 通知,从而感知到某个节点断开,并立即开始容错工作。

按照上面所说,那为什么HBase不直接让HMaster来负责RegionServer的监控呢?如果HMaster直接通过心跳机制等来管理RegionServer的状态,随着集群越来越大,HMaster的管理负担会越来越重,另外它自身也有挂掉的可能,因此数据还需要持久化。在这种情况下,ZooKeeper就成了理想的选择。

三,Region管理

对于大的HBase集群来说,Region的数量可能会多达十万级别,甚至更多,这样规模的Region状态管理交给ZooKeeper来做也是一个非常nice的选择。

四,分布式SplitWAL任务管理

当某台RegionServer服务器挂掉时,由于总有一部分新写入的数据还没有持久化到HFile中,因此在迁移该RegionServer的服务时,一个重要的工作就是从WAL中恢复这部分还在内存中的数据,而这部分工作最关键的一步就是SplitWAL,即HMaster需要遍历该RegionServer服务器的WAL,并按Region切分成小块移动到新的地址下,并进行日志的回放(replay)。

由于单个RegionServer的日志量相对庞大(可能有上千个Region,上GB的日志),而用户又往往希望系统能够快速完成日志的恢复工作。因此一个可行的方案是将这个处理WAL的任务分给多台RegionServer服务器来共同处理,而这就又需要一个持久化组件来辅助HMaster完成任务的分配。当前的做法是,HMaster会在ZooKeeper上创建一个SplitWAL节点(默认情况下,是/hbase/SplitWAL节点),将“哪个RegionServer处理哪个Region”这样的信息以列表的形式存放到该节点上,然后由各个RegionServer服务器自行到该节点上去领取任务并在任务执行成功或失败后再更新该节点的信息,以通知HMaster继续进行后面的步骤。ZooKeeper在这里担负起了分布式集群中相互通知和信息持久化的角色。



综上,就是ZooKeeper在HBase中的应用,在这里只列举出了一部分,相对说比较突出的作用,其实ZooKeeper在HBase中的应用远不止这些,比如HMaster还依赖ZooKeeper来完成Table的enable/disable状态记录,以及HBase中几乎所有的元数据存储都是放在ZooKeeper上的等等。

ZooKeeper分布式集群部署及问题

    ZooKeeper为分布式应用系统提供了高性能服务,在很多常见的集群服务中被广泛使用,最常见的当属HBase集群了,其它的还有Solr集群,Hadoop-2中的HA自动故障转移等。本文主要介绍了为HBase集群部署ZooKeeper集群的过程,并说明了部署过程中遇到的问题。

    默认情况下,由HBase管理ZooKeeper的启动和停止,要想修改这一默认行为,需要将hbase-env.sh中的export HBASE_MANAGES_ZK=true改为export HBASE_MANAGES_ZK=false,并在启动HBase之前先启动ZooKeeper集群。在$ZOOKEEPER_HOME/conf中复制zoo_sample.cfg为zoo.cfg,并修改dataDir为用于保存ZooKeeper数据的目录,默认为/tmp/zookeeper。然后添加用于集群的服务器,格式为:server.1=hostname1:连接端口:选举端口,其中的1为myid文件中的值。比如对于拥有三个节点的ZooKeeper集群,示例配置可能为:

server.1=CentOS-1:2888:3888
server.2=CentOS-2:2888:3888
server.3=CentOS-3:2888:3888
    对于ZooKeeper集群配置,需要在启动集群之前在$ZOOKEEPER_HOME/$dataDir下创建myid文件,文件内容与server.x中的x对应,比如myid位于上述示例中的CentOS-1中,则内容必须为1。CentOS-2、CentOS-3上的myid文件内容分别为2、3。如果在集群启动之前没有创建myid文件,在启动时会报如下的错误:
2015-07-03 15:37:40,877 [myid:] - ERROR [main:QuorumPeerMain@85] - Invalid config, exiting abnormally
org.apache.zookeeper.server.quorum.QuorumPeerConfig$ConfigException: Error processing /home/search/zookeeper-3.4.6/bin/../conf/zoo.cfg
at org.apache.zookeeper.server.quorum.QuorumPeerConfig.parse(QuorumPeerConfig.java:123)
at org.apache.zookeeper.server.quorum.QuorumPeerMain.initializeAndRun(QuorumPeerMain.java:101)
at org.apache.zookeeper.server.quorum.QuorumPeerMain.main(QuorumPeerMain.java:78)
Caused by: java.lang.IllegalArgumentException: /HData/zookeeper/myid file is missing
at org.apache.zookeeper.server.quorum.QuorumPeerConfig.parseProperties(QuorumPeerConfig.java:350)
at org.apache.zookeeper.server.quorum.QuorumPeerConfig.parse(QuorumPeerConfig.java:119)
... 2 more
Invalid config, exiting abnormally

    在每台ZooKeeper节点对ZooKeeper进行修改完毕后,由于ZooKeeper没有start-hbase或者start-dfs类似的启动所有节点的脚本,所以必须在每台服务器上分别执行$ZOOKEEPER_HOME/bin/zkServer.sh start启动ZooKeeper。启动完毕后可以执行$ZOOKEEPER_HOME/bin/zkServer.sh status检查状态,比如:

JMX enabled by default
Using config: /application/search/zookeeper/bin/../conf/zoo.cfg
Mode: follower

    ZooKeeper集群成功启动后,需要修改hbase-site.xml中的参数hbase.zookeeper.quorum,使其值包含所有ZooKeeper节点,比如CentOS-1,CentOS-2,CentOS-3,之间用逗号分隔。

    而对于单节点的ZooKeeper来说,则不需要在配置文件zoo.cfg中设置服务器相关的信息,即不需要设置server.x,因而也就无需创建对应的myid文件。对于单节点的ZooKeeper还有一个问题需要注意,该问题属于ZooKeeper本身的一个Bug,但已经在版本3.4.7, 3.5.2, 3.6.0中修复,具体可参考ZOOKEEPER-832,异常信息如下:

2015-07-22 13:00:23,286 [myid:] - INFO  [NIOServerCxn.Factory:0.0.0.0/0.0.0.0:2181:NIOServerCnxnFactory@213] - Accepted socket connection from /10.10.32.223:15489
2015-07-22 13:00:23,286 [myid:] - INFO  [NIOServerCxn.Factory:0.0.0.0/0.0.0.0:2181:ZooKeeperServer@811] - Refusing session request for client /10.10.32.223:15489 as it has seen zxid 0x210d711 our last zxid is 0x26ca client must try another server
2015-07-22 13:00:23,287 [myid:] - INFO  [NIOServerCxn.Factory:0.0.0.0/0.0.0.0:2181:NIOServerCnxn@1000] - Closed socket connection for client /10.10.32.223:15489 (no session established for client)

    该问题是由于修改了ZooKeeper的$dataDir目录到新目录或者删除目录中的文件引起的。

    在部署ZooKeeper时还遇到了日志输出的问题,在不做任何与日志有关的修改时,会将ZooKeeper日志输出到单一的zookeeper.out文件,如果长时间运行,将导致该文件非常巨大,对其查看将非常不方便,因此需要修改zkEnv.sh、log4j.properties。对zkEnv.sh做如下的修改,分别指定日志保存的目录,日志输出的级别及输出的地方:

if [ "x$ZOO_LOG_DIR" = "x" ]
then
    #ZOO_LOG_DIR="." #默认值为当前目录
    ZOO_LOG_DIR="/HData/log/zookeeper/"
fi
if [ "x$ZOO_LOG4J_PROP" = "x" ]
then
    #ZOO_LOG4J_PROP="INFO,CONSOLE"
    ZOO_LOG4J_PROP="INFO,ROLLINGFILE"
fi

    然后修改log4j.properties文件,注释部分为原有值,新增部分取代了原有值:

#zookeeper.root.logger=INFO, CONSOLE
zookeeper.root.logger=INFO.ROLLINGFILE #日志输出的级别及输出的地方
#log4j.appender.ROLLINGFILE=org.apache.log4j.RollingFileAppender
log4j.appender.ROLLINGFILE=org.apache.log4j.DailyRollingFileAppender #日志文件的appender
# Max log file size of 10MB
#log4j.appender.ROLLINGFILE.MaxFileSize=10MB #禁用该属性
# uncomment the next line to limit number of backup files
#log4j.appender.ROLLINGFILE.MaxBackupIndex=10

    做完上述部分的修改后,ZooKeeper将日志输出到$ZOO_LOG_DIR/zookeeper.log中,每天都会生成新的日志文件,并将之前的文件重命名为zookeeper.log.2015-07-22。即使做了上述修改依然会生成zookeeper.out,尽管此时该文件的内容为空,但对于不喜欢该文件的用户来说,则需要修改zkServer.sh文件,将下面的行替换如下,这样就不会在日志目录中存在zookeeper.out文件。

nohup "$JAVA" "-Dzookeeper.log.dir=$ZOO_LOG_DIR" "-Dzookeeper.root.logger=$ZOO_LOG4J_PROP" \\
-cp "$CLASSPATH" $JVMFLAGS $ZOOMAIN "$ZOOCFG" > "$_ZOO_DAEMON_OUT" 2>&1 < /dev/null &

nohup $JAVA "-Dzookeeper.log.dir=$ZOO_LOG_DIR" "-Dzookeeper.root.logger=$ZOO_LOG4J_PROP" \\
    -cp "$CLASSPATH" $JVMFLAGS $ZOOMAIN "$ZOOCFG" > /dev/null 2>&1 < /dev/null &

    本文简要描述了ZooKeeper集群的部署安装,并分析了安装过程中遇到的问题,最后说明了如何修改ZooKeeper的默认日志配置,以使日志输出到指定目录和文件中。

以上是关于ZooKeeper在HBase中的应用的主要内容,如果未能解决你的问题,请参考以下文章

01.zookeeper介绍 (中级Java程序员必备技能一)

ZooKeeper原理及其在Hadoop和HBase中的应用

走进大数据 | ZooKeeper 原理及其在 Hadoop 和 HBase 中的应用

面试官:你知道zookeeper有哪些作用吗?

数据流行Zookeeper典型应用场景介绍

一起走进动物园管理员——ZooKeeper