HBase 1.2.6 完全分布式部署

测试环境中用三台 Linux 服务器来部署 HBase 与 Hadoop,详细信息如下:

hostname ip role hadoop hbase
yibo-0 10.10.5.215 master ResourceManager/NameNode/SecondaryNameNode HMaster
yibo-1 10.10.5.207 slave1 NodeManager/DataNode HRegionServer
yibo-2 10.10.5.217 slave2 NodeManager/DataNode HRegionServer

对于 HBase 与 Hadoop 版本要选择相对应的(否则会出很多问题),具体对应版本可参考:

http://hbase.apache.org/book.html#configuration

本次集群对应版本为:Hadoop-2.7.3 + HBase-1.2.6

Hadoop

准备工作

  1. 安装 JDK,略过,我的环境如下
    export JAVA_HOME=/opt/j2sdk

  2. 添加一个 hadoop 用户,用来运行 hadoop 集群

    1
    2
    3
    groupadd hadoop
    useradd -g hadoop hadoop
    # echo "password" | passwd --stdin hadoop
  3. 三台机器之间做双机互信,原因 master 通过远程启动 datanode 进程和 tasktracker 进程,如果不做双机互信,会导致每次启动集群服务都会需要密码。

    如果是使用 Kerberos 的话,执行cp /root/.k5login /home/hadoop/

  4. 同步时间

    1
    */5 * * * * /usr/sbin/ntpdate ntp.api.bz &> /dev/null
  5. 创建相关文件夹并授权

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    mkdir -p /data/hadoop/hdfs/name
    mkdir -p /data/hadoop/hdfs/data
    mkdir -p /data/hadoop/tmp
    mkdir -p /data/hadoop/logs/hadoop
    mkdir -p /data/hadoop/logs/hbase

    mkdir -p /var/hadoop/pids

    ln -s /opt/hadoop-2.7.3 /opt/hadoop

    chown -R hadoop:hadoop /opt/hadoop
    chown -R hadoop:hadoop /opt/hadoop-2.7.3
    chown -R hadoop:hadoop /data/hadoop
    chmod 777 /data/hadoop

配置

  1. 配置文件说明(Hadoop 的配置文件都存储在$HADOOP_HOME/etc/hadoop下)

    hadoop-env.sh 用于定义 hadoop 运行环境相关的配置信息,比如配置 JAVA_HOME 环境变量、为 hadoop 的 JVM 指定特定的选项、指定日志文件所在的目录路径以及 master 和 slave 文件的位置等;
    core-site.xml 用于定义系统级别的参数,它作用于全部进程及客户端,如 HDFS URL、Hadoop 的临时目录以及用于 rack-aware 集群中的配置文件的配置等,此中的参数定义会覆盖 core-default.xml 文件中的默认配置;
    hdfs-site.xml HDFS 的相关设定,如文件副本的个数、块大小及是否使用强制权限等,此中的参数定义会覆盖 hdfs-default.xml 文件中的默认配置;
    mapred-site.xml mapreduce 的相关设定,如 reduce 任务的默认个数、任务所能够使用内存的默认上下限等,此中的参数定义会覆盖 mapred-default.xml 文件中的默认配置;
    slaves Hadoop 集群的 slave(datanode)和 tasktracker 的主机列表,master 启动时会通过 SSH 连接至此列表中的所有主机并为其启动 DataNode 和 taskTracker 进程;
    hadoop-metrics2.properties 控制 metrics 在 hadoop 上如何发布属性
    log4j.properties 系统日志文件、namenode 审计日志、tarsktracker 子进程的任务日志属性

  2. 配置 Hadoop 环境变量/etc/profile

    1
    2
    3
    4
    5
    echo "export HADOOP_HOME=/opt/hadoop" >> /etc/profile
    echo "export PATH=$HADOOP_HOME/bin:$PATH" >> /etc/profile
    echo "export HADOOP_CONF_DIR=$HADOOP_HOME/etc/hadoop" >> /etc/profile
    echo "export YARN_CONF_DIR=$HADOOP_HOME/etc/hadoop" >> /etc/profile
    source /etc/profile
  3. 配置 hadoop-env.sh

    1
    2
    3
    4
    export JAVA_HOME=/opt/j2sdk

    export HADOOP_PID_DIR=/var/hadoop/pids
    export HADOOP_SECURE_DN_PID_DIR=/var/hadoop/pids
  4. 配置 mapred-env.sh

    1
    export HADOOP_MAPRED_PID_DIR=/var/hadoop/pids
  5. 配置 yarn-env.sh

    1
    export YARN_PID_DIR=/var/hadoop/pids
  6. 配置 core-site.xml

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    <configuration>
    <!-- 指定hdfs的nameservice为ns1 -->
    <property>
    <name>fs.defaultFS</name>
    <value>hdfs://yibo-0:9000</value>
    </property>
    <!-- Size of read/write buffer used in SequenceFiles. -->
    <property>
    <name>io.file.buffer.size</name>
    <value>131072</value>
    </property>
    <!-- 指定hadoop临时目录,自行创建 -->
    <property>
    <name>hadoop.tmp.dir</name>
    <value>/data/hadoop/tmp</value>
    </property>
    </configuration>
  7. 配置 hdfs-site.xml

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    <configuration>
    <property>
    <name>dfs.namenode.secondary.http-address</name>
    <value>yibo-0:50090</value>
    </property>
    <!-- 保存副本的数量,默认是保存3份,由于这里只有两台slave。所以设置2 -->
    <property>
    <name>dfs.replication</name>
    <value>2</value>
    </property>
    <property>
    <name>dfs.namenode.name.dir</name>
    <value>file:/data/hadoop/hdfs/name</value>
    </property>
    <property>
    <name>dfs.datanode.data.dir</name>
    <value>file:/data/hadoop/hdfs/data</value>
    </property>
    <!-- hbase的配置里要求这么设置的 -->
    <property>
    <name>dfs.datanode.max.transfer.threads</name>
    <value>4096</value>
    </property>
    </configuration>
  8. 配置 mapred-site.xml

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    <configuration>
    <property>
    <name>mapreduce.framework.name</name>
    <value>yarn</value>
    </property>
    <property>
    <name>mapreduce.jobhistory.address</name>
    <value>yibo-0:10020</value>
    </property>
    <property>
    <name>mapreduce.jobhistory.address</name>
    <value>yibo-0:19888</value>
    </property>
    </configuration>
  9. 配置 yarn-site.xml

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    <configuration>

    <!-- Site specific YARN configuration properties -->
    <!-- Configurations for ResourceManager -->
    <property>
    <name>yarn.nodemanager.aux-services</name>
    <value>mapreduce_shuffle</value>
    </property>
    <property>
    <name>yarn.resourcemanager.address</name>
    <value>yibo-0:8032</value>
    </property>
    <property>
    <name>yarn.resourcemanager.scheduler.address</name>
    <value>yibo-0:8030</value>
    </property>
    <property>
    <name>yarn.resourcemanager.resource-tracker.address</name>
    <value>yibo-0:8031</value>
    </property>
    <property>
    <name>yarn.resourcemanager.admin.address</name>
    <value>yibo-0:8033</value>
    </property>
    <property>
    <name>yarn.resourcemanager.webapp.address</name>
    <value>yibo-0:8088</value>
    </property>
    </configuration>
  10. 配置 slaves 文件,增加 slave 主机名

    1
    2
    yibo-1
    yibo-2
  11. 复制 Hadoop 配置好的包到其他 Linux 主机

    1
    scp -r hadoop-2.7.3 root@host:/opt/

    生产环境下注意对 logs 做软连接

    1
    rm -rf /opt/hadoop/logs; ln -s /data/hadoop/logs/hadoop /opt/hadoop/logs
  12. 格式化节点(在 yibo-0 上执行)

    1
    hdfs namenode -format

    显示如下就是成功了
    hadoop-format

  13. 启动集群(用 root 用户就行)

    1
    /opt/hadoop/sbin/start-all.sh
  14. 查看

    http://yibo-0:8088/

可能遇见的问题

权限问题:

1
chown -R hadoop:hadoop /opt/hadoop-2.7.3

解析:将 hadoop-2.7.3 文件属主、组更换为 hadoop:hadoop

1
chmod 777 hadoop

解析:将 hadoop 文件权限变成 421 421 421 可写、可读可、执行即 7 7 7

HBase

  1. 环境变量/etc/profile

    1
    2
    echo "export HBASE_HOME=/opt/hbase" >> /etc/profile
    source /etc/profile
  2. 创建相关文件夹

    1
    2
    mkdir -p /data/hadoop/hbase/tmp
    chown -R hadoop:hadoop /data/hadoop
  3. 配置 hbase-env.sh

    1
    2
    3
    4
    5
    6
    export JAVA_HOME=/opt/j2sdk
    # Add a pointer to your HADOOP_CONF_DIR to the HBASE_CLASSPATH environment variable in hbase-env.sh.
    export HBASE_CLASSPATH=/opt/hadoop/etc/hadoop/
    # Tell HBase whether it should manage its own instance of ZooKeeper or not.
    export HBASE_MANAGES_ZK=false
    export HBASE_PID_DIR=/var/hadoop/pids
  4. 配置 hbase-site.xml

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    <configuration>
    <!-- 指定hbase在HDFS上存储的路径 -->
    <property>
    <name>hbase.rootdir</name>
    <value>hdfs://yibo-0:9000/hbase</value>
    </property>
    <!-- 指定hbase是分布式的 -->
    <property>
    <name>hbase.cluster.distributed</name>
    <value>true</value>
    </property>
    <!-- 指定zk的地址,多个用“,”分割 -->
    <property>
    <name>hbase.zookeeper.quorum</name>
    <value>yibo-0,yibo-1,yibo-2</value>
    </property>
    <property>
    <name>hbase.zookeeper.property.clientPort</name>
    <value>2181</value>
    </property>
    <property>
    <name>hbase.zookeeper.property.dataDir</name>
    <value>/data/zookeeper/data</value>
    </property>
    <property>
    <name>hbase.tmp.dir</name>
    <value>/data/hadoop/hbase/tmp</value>
    </property>
    </configuration>

外网的记得配置hbase.regionserver.info.bindAddress

  1. 配置 regionservers

    1
    2
    yibo-1
    yibo-2
  2. 替换 Hadoop 的 jar 包
    《HBase 权威指南》中有这么一段:
    由于 HBase 依赖于 Hadoop,它要求 Hadoop 的 JAR 必须部署在 HBase 的 lib 目录下。默认依赖的 Hadoop 的 JAR 是从 Apache branch-0.20-append 这个分支编译出来的。关键之处在于 HBase 使用的 Hadoop 版本必须与底层 Hadoop 集群上使用的 Hadoop 版本一致,使用 Hadoop 集群正在运行的 JAR(hadoop-xyz.jar )替换 HBase 的 lib 目录中依赖的 Hadoop 的 JAR 可以避免版本不匹配问题,此外必须确认集群中所有的节点都需要更新为一样的 JAR,否则版本不匹配问题会造成集群无法启动或假死现象。
    虽说我之前是使用默认依赖部署过全分布式,没有发现什么问题,但是,肯定还是替换一下的好
    先查看一下 HBase 的 lib 目录

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    $ ls lib |grep hadoop
    hadoop-annotations-2.5.1.jar
    hadoop-auth-2.5.1.jar
    hadoop-client-2.5.1.jar
    hadoop-common-2.5.1.jar
    hadoop-hdfs-2.5.1.jar
    hadoop-mapreduce-client-app-2.5.1.jar
    hadoop-mapreduce-client-common-2.5.1.jar
    hadoop-mapreduce-client-core-2.5.1.jar
    hadoop-mapreduce-client-jobclient-2.5.1.jar
    hadoop-mapreduce-client-shuffle-2.5.1.jar
    hadoop-yarn-api-2.5.1.jar
    hadoop-yarn-client-2.5.1.jar
    hadoop-yarn-common-2.5.1.jar
    hadoop-yarn-server-common-2.5.1.jar
    hbase-hadoop2-compat-1.2.6.jar
    hbase-hadoop-compat-1.2.6.jar

    看到它是基于 Hadoop2.5.1 的,所以我们需要用我们的 Hadoop2.7.3 下的 jar 包来替换 2.5.1 的,保证版本的一致性,Hadoop 下的 jar 包都是在$HADOOP_HOME/share/hadoop 下的.

    我们先进入到$HBASE_HOME/lib 下运行命令:rm -rf hadoop*.jar删掉所有的 Hadoop 相关的 jar 包,然后运行:

    1
    find $HADOOP_HOME/share/hadoop -name "hadoop*jar" | xargs -i cp {} $HBASE_HOME/lib/

    拷贝所有 Hadoop2.7.3 下的 jar 包到 HBase 下进行 Hadoop 版本的统一

  3. 分发到其他机器上

    生产环境下注意对 logs 做软连接

    1
    rm -rf /opt/hbase/logs; ln -s /data/hadoop/logs/hbase /opt/hbase/logs
  4. 启动

    1
    /opt/hbase/bin/start-hbase.sh
  5. 检查

    http://yibo-0:16010/

API

http://hbase.apache.org/apidocs/index.html

可能会遇到这个错误:

1
Caused by: java.lang.IllegalAccessError: tried to access method com.google.common.base.Stopwatch.<init>()V from class org.apache.hadoop.hbase.zookeeper.MetaTableLocator

这是因为 guava 的 12 vs 18,Constructors 发生了变化(com.google.common.base.Stopwatch 类的不能直接 new 了,构造函数去除了 public)。我的项目中目前使用的是 guava 18,hbase 用的还是 11.0.2、12.0.1 版本的。(另外 Protobuf 也会冲突,2.5.0 vs 3.3.1)

解决办法有多种:

  1. 使用 maven 插件 maven-shade-plugin http://blog.csdn.net/sunshine920103/article/details/51659936
  2. 直接修改 guava 18 的源代码 https://my.oschina.net/u/1404252/blog/814260
  3. 升级 hbase 的依赖 http://housong.github.io/2016/版本兼容性问题/
  4. 单独再开个工程,不再依赖(或间接依赖)guava

我最终采取的解决办法:修改 guava 18 的源码,重新打 jar 包,上传到了 maven 私服的 thirdparty,将 thirdparty 的优先级调到 maven 中央仓库的前边,删除掉本地仓库已经下载下来的 jar 包,重新导入 Maven 依赖。

2017-07-05 UPDATE:采取上边的解决方案后,还是出现了异常。现已改为使用hbase-shaded-client依赖。

1
2
3
4
5
<dependency>
<groupId>org.apache.hbase</groupId>
<artifactId>hbase-shaded-client</artifactId>
<version>${hbase-version}</version>
</dependency>