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
  1. 三台机器之间做双机互信,原因master通过远程启动 datanode 进程和 tasktracker 进程,如果不做双机互信,会导致每次启动集群服务都会需要密码。

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

  2. 同步时间

1
*/5 * * * * /usr/sbin/ntpdate ntp.api.bz &> /dev/null
  1. 创建相关文件夹并授权
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
export HADOOP_HOME="/opt/hadoop"
export PATH="$HADOOP_HOME/bin:$PATH"
export HADOOP_CONF_DIR=$HADOOP_HOME/etc/hadoop
export YARN_CONF_DIR=$HADOOP_HOME/etc/hadoop

source /etc/profile

  1. 配置 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
  1. 配置 mapred-env.sh
1
export HADOOP_MAPRED_PID_DIR=/var/hadoop/pids
  1. 配置 yarn-env.sh
1
export YARN_PID_DIR=/var/hadoop/pids
  1. 配置 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>
  1. 配置 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>
  1. 配置 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>
  1. 配置 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>
  1. 配置slaves文件,增加slave主机名
1
2
yibo-1
yibo-2
  1. 复制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
  1. 格式化节点(在 yibo-0 上执行)
1
hdfs namenode -format
显示如下就是成功了![hadoop-format](https://ws1.sinaimg.cn/large/6e3b2269ly1fq0fasmnb0j21kw0gv4bw)
  1. 启动集群(用 root 用户就行)
1
/opt/hadoop/sbin/start-all.sh
  1. 查看

    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
export HBASE_HOME=/opt/hbase

source /etc/profile

  1. 创建相关文件夹
1
2
mkdir -p /data/hadoop/hbase/tmp
chown -R hadoop:hadoop /data/hadoop
  1. 配置 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
  1. 配置 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
  1. 替换 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
    [root@yibo-0 hbase]# 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版本的统一

  2. 分发到其他机器上

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

1
rm -rf /opt/hbase/logs; ln -s /data/hadoop/logs/hbase /opt/hbase/logs
  1. 启动
1
/opt/hbase/bin/start-hbase.sh
  1. 检查

    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>