Hbase 是一个构建在Hadoop文件系统之上的面向列的数据管理系统。
要想明白为什么产生HBase,就需要先了解一下Hadoop存在的限制?Hadoop可以通过HDFS来存储结构化、半结构甚至非结构化的数据,它是传统数据库的补充,是海量数据存储的最佳方法,它针对大文件的存储,批量访问和流式访问都做了很好的优化,同时也通过多个副本解决了容灾问题。
但是Hadoop 的缺陷在于它只能执行批处理,并且只能以顺序方式访问数据,这意味着即使是最简单的工作,也必须搜索整个数据集,无法实现对数据的随机访问,实现数据的随机访问是传统的关系型数据库所擅长的,但它们却不能用于海量数据的存储。在这种情况下,必选有一种新的方案来解决海量数据存储和随机访问的问题,HBase就是其中之一(HBase,Cassandra,counchDB,Dynamo和MongoDB都能存储海量数据并支持随机访问)。
注:数据结构分类:
- 结构化数据:即以关系型数据库表形式管理的数据;
- 半结构化数据:非关系模型,有基本固定结构模式的数据,例如日志文件、XML文档、JSON文档、Email等;
- 非结构化数据:没有固定的数据模式,如WORD、PDF、PPT、EXL,各种格式图片、视频等。
HBase 是一种类似于Google‘s Big Table
的数据模型,它是Hadoop生态系统的一部分,它将数据存储在HDFS上,客户端可以通过HBase实现对HDFS上数据的随机访问。它具有以下特性:
HBase 是一个面向列族
的数据库管理系统。表schema
仅定义列族,表具有多个列族,每个列族可以包含任意数据量的列,列由多个单元格(cell)组成,单元格可以存储多个版本的数据,多个版本数据以时间戳进行区分。
下图为HBase 中一张表:
Rowkey
的字典序列进行排序;personal
和office
;personal
拥有name、city、phone三个列,列族office
拥有tel、address两个列。Phoenix
是HBase 的开源 SQL 中间层,它允许你使用标准JDBC的方式来操作HBase上的数据。在Phoenix
之前,如果你要访问HBase,只能调用它的Java API,但相比于使用一行SQL就能是想数据查询,HBase 的API还是过于复杂。Phoenix
的理念是 we put SQL back in NoSQL
,即你可以使用标准的SQL就能完成对HBase上数据的操作。同时这也意味着你可以通过集成Spring Data JPA
或Mybatis
等常用的持久层框架来操作HBase。
其次Phoenix
的性能表现也非常优异,Phoenix
查询引擎会将 SQL 查询转换为一个或多个 HBase Scan,通过并行执行来生成标准的 JDBC 结果集。它通过直接使用 HBase API 以及协处理器和自定义过滤器,可以为小型数据查询提供毫秒级的性能,为千万行数据的查询提供秒级的性能。同时 Phoenix
还拥有二级索引等 HBase 不具备的特性,因为以上的优点,所以 Phoenix
成为了 HBase 最优秀的 SQL 中间层。
Standalone模式和伪集群模式的区别
Standalone
模式下,所有守护进程都运行在一个 jvm 进程/实例中;HMaster
,HRegionServer
和 ZooKeeper
) 则分别作为一个单独的进程运行。说明:两种模式任选其一进行部署即可,对于开发测试来说区别不大。
2.1 下载并解压
从官方网站 下载所需要版本的二进制安装包,并进行解压:
# tar -zxvf hbase-2.1.4-bin.tar.gz
2.2 配置环境变量
# vim /etc/profile
添加环境变量:
export HBASE_HOME=/usr/app/hbase-2.1.4
export PATH=$HBASE_HOME/bin:$PATH
使得配置的环境变量生效:
# source /etc/profile
2.3 进行HBase相关配置
修改安装目录下的 conf/hbase-env.sh
,指定 JDK 的安装路径:
# The java implementation to use. Java 1.8+ required.
export JAVA_HOME=/usr/java/jdk1.8.0_201
修改安装目录下的 conf/hbase-site.xml
,增加如下配置:
<configuration>
<property>
<name>hbase.rootdir</name>
<value>file:///home/hbase/rootdir</value>
</property>
<property>
<name>hbase.zookeeper.property.dataDir</name>
<value>/home/zookeeper/dataDir</value>
</property>
<property>
<name>hbase.unsafe.stream.capability.enforce</name>
<value>false</value>
</property>
</configuration>
hbase.rootdir:
配置 hbase
数据的存储路径;
hbase.zookeeper.property.dataDir:
配置 zookeeper
数据的存储路径;
hbase.unsafe.stream.capability.enforce:
使用本地文件系统存储,不使用 HDFS
的情况下需要禁用此配置,设置为 false
。
2.4 启动HBase
由于已经将 HBase 的 bin
目录配置到环境变量,直接使用以下命令启动:
# start-hbase.sh
2.5 验证启动是否成功
验证方式一 :使用 jps
命令查看 HMaster
进程是否启动。
[root@hadoop001 hbase-2.1.4]# jps
16336 Jps
15500 HMaster
验证方式二 :访问 HBaseWeb UI 页面,默认端口为 16010
:
3.1 Hadoop单机伪集群安装
这里我们采用 HDFS 作为 HBase 的存储方案,需要预先安装 Hadoop
。Hadoop 的安装方式单独整理至:
Hadoop 单机伪集群搭建
3.2 Hbase版本选择
HBase 的版本必须要与 Hadoop 的版本兼容,不然会出现各种 Jar 包冲突。这里Hadoop 安装的版本为 hadoop-2.6.0-cdh5.15.2
,为保持版本一致,选择的 HBase 版本为 hbase-1.2.0-cdh5.15.2
。所有软件版本如下:
hadoop-2.6.0-cdh5.15.2
hbase-1.2.0-cdh5.15.2
JDK 1.8
3.3 软件下载解压
下载后进行解压,下载地址:http://archive.cloudera.com/cdh5/cdh/5/
# tar -zxvf hbase-1.2.0-cdh5.15.2.tar.gz
3.4 配置环境变量
# vim /etc/profile
添加环境变量:
export HBASE_HOME=/usr/app/hbase-1.2.0-cdh5.15.2
export PATH=$HBASE_HOME/bin:$PATH
使得配置的环境变量生效:
# source /etc/profile
3.5 进行HBase相关配置
1.修改安装目录下的 conf/hbase-env.sh
,指定 JDK 的安装路径:
# The java implementation to use. Java 1.7+ required.
export JAVA_HOME=/usr/java/jdk1.8.0_201
2.修改安装目录下的 conf/hbase-site.xml
,增加如下配置 (hadoop001
为主机名):
<configuration>
<!--指定 HBase 以分布式模式运行-->
<property>
<name>hbase.cluster.distributed</name>
<value>true</value>
</property>
<!--指定 HBase 数据存储路径为 HDFS 上的 hbase 目录,hbase 目录不需要预先创建,程序会自动创建-->
<property>
<name>hbase.rootdir</name>
<value>hdfs://hadoop001:8020/hbase</value>
</property>
<!--指定 zookeeper 数据的存储位置-->
<property>
<name>hbase.zookeeper.property.dataDir</name>
<value>/home/zookeeper/dataDir</value>
</property>
</configuration>
3.修改安装目录下的 conf/regionservers
,指定 region servers
的地址,修改后其内容如下:
hadoop001
3.6 启动
# bin/start-hbase.sh
3.7 验证启动是否成功
验证方式一 :使用 jps
命令查看进程。其中 HMaster
,HRegionServer
是 HBase 的进程,HQuorumPeer
是 HBase 内置的 Zookeeper
的进程,其余的为 HDFS
和 YARN
的进程。
[root@hadoop001 conf]# jps
28688 NodeManager
25824 GradleDaemon
10177 Jps
22083 HRegionServer
20534 DataNode
20807 SecondaryNameNode
18744 Main
20411 NameNode
21851 HQuorumPeer
28573 ResourceManager
21933 HMaster
验证方式二 :访问 HBase Web UI 界面,需要注意的是 1.2
版本的 HBase 的访问端口为 60010
:
这里搭建一个 3 节点的 HBase 集群,其中三台主机上均为 Regin Server
。同时为了保证高可用,除了在 hadoop001
上部署主 Master 服务外,还在 hadoop002
上部署备用的 Master
服务。Master
服务由 Zookeeper
集群进行协调管理,如果主 Master
不可用,则备用 Master
会成为新的主 Master
。
HBase
的运行需要依赖 Hadoop
和 JDK(HBase 2.0+ 对应 JDK 1.8+)
。同时为了保证高可用,这里我们不采用 HBase
内置的 Zookeeper
服务,而采用外置的 Zookeeper
集群。相关搭建步骤可以参阅:
3.1 下载并解压
下载并解压,这里我下载的是 CDH 版本 HBase,下载地址为:http://archive.cloudera.com/cdh5/cdh/5/
# tar -zxvf hbase-1.2.0-cdh5.15.2.tar.gz
3.2 配置环境变量
# vim /etc/profile
添加环境变量:
export HBASE_HOME=usr/app/hbase-1.2.0-cdh5.15.2
export PATH=$HBASE_HOME/bin:$PATH
使得配置的环境变量立即生效:
# source /etc/profile
3.3 集群配置
进入 ${HBASE_HOME}/conf
目录下,修改配置:
# 配置JDK安装位置
export JAVA_HOME=/usr/java/jdk1.8.0_201
# 不使用内置的zookeeper服务
export HBASE_MANAGES_ZK=false
<configuration>
<property>
<!-- 指定 hbase 以分布式集群的方式运行 -->
<name>hbase.cluster.distributed</name>
<value>true</value>
</property>
<property>
<!-- 指定 hbase 在 HDFS 上的存储位置 -->
<name>hbase.rootdir</name>
<value>hdfs://hadoop001:8020/hbase</value>
</property>
<property>
<!-- 指定 zookeeper 的地址-->
<name>hbase.zookeeper.quorum</name>
<value>hadoop001:2181,hadoop002:2181,hadoop003:2181</value>
</property>
</configuration>
hadoop001
hadoop002
hadoop003
hadoop002
backup-masters
这个文件是不存在的,需要新建,主要用来指明备用的 master
节点,可以是多个,这里我们以 1
个为例。
3.4 HDFS客户端配置
这里有一个可选的配置:如果您在 Hadoop 集群上进行了 HDFS
客户端配置的更改,比如将副本系数 dfs.replication
设置成 5
,则必须使用以下方法之一来使 HBase
知道,否则 HBase
将依旧使用默认的副本系数 3
来创建文件:
Add a pointer to your
HADOOP_CONF_DIR
to theHBASE_CLASSPATH
environment variable inhbase-env.sh
. Add a copy of hdfs-site.xml (or
hadoop-site.xml) or, better, symlinks, under${HBASE_HOME}/conf
, or if
only a small set of HDFS client configurations, add them to
hbase-site.xml.
以上是官方文档的说明,这里解释一下:
第一种 :将 Hadoop
配置文件的位置信息添加到 hbase-env.sh
的 HBASE_CLASSPATH
属性,示例如下:
export HBASE_CLASSPATH=usr/app/hadoop-2.6.0-cdh5.15.2/etc/hadoop
第二种 :将 Hadoop
的 hdfs-site.xml
或 hadoop-site.xml
拷贝到 ${HBASE_HOME}/conf
目录下,或者通过符号链接的方式。如果采用这种方式的话,建议将两者都拷贝或建立符号链接,示例如下:
# 拷贝
cp core-site.xml hdfs-site.xml /usr/app/hbase-1.2.0-cdh5.15.2/conf/
# 使用符号链接
ln -s /usr/app/hadoop-2.6.0-cdh5.15.2/etc/hadoop/core-site.xml
ln -s /usr/app/hadoop-2.6.0-cdh5.15.2/etc/hadoop/hdfs-site.xml
注:hadoop-site.xml 这个配置文件现在叫做 core-site.xml
第三种 :如果你只有少量更改,那么直接配置到 hbase-site.xml
中即可。
3.5 安装包分发
将 HBase
的安装包分发到其他服务器,分发后建议在这两台服务器上也配置一下 HBase
的环境变量。
scp -r /usr/app/hbase-1.2.0-cdh5.15.2/ hadoop002:usr/app/
scp -r /usr/app/hbase-1.2.0-cdh5.15.2/ hadoop003:usr/app/
4.1 启动ZooKeeper集群
分别到三台服务器上启动 ZooKeeper
服务:
zkServer.sh start
4.2 启动Hadoop集群
# 启动dfs服务
start-dfs.sh
# 启动yarn服务
start-yarn.sh
4.3 启动HBase集群
进入 hadoop001
的 ${HBASE_HOME}/bin
,使用以下命令启动 HBase
集群。执行此命令后,会在 hadoop001
上启动 Master
服务,在 hadoop002
上启动备用 Master
服务,在 regionservers
文件中配置的所有节点启动 region server
服务。
start-hbase.sh
4.5 查看服务
访问 HBase
的 Web-UI 界面,这里我安装的 HBase
版本为 1.2
,访问端口为 60010
,如果你安装的是 2.0
以上的版本,则访问端口号为 16010
。可以看到 Master
在 hadoop001
上,三个 Regin Servers
分别在 hadoop001
,hadoop002
,和 hadoop003
上,并且还有一个 Backup Matser
服务在 hadoop002
上。
hadoop002
上的 HBase
出于备用状态:
我们可以按照官方安装说明进行安装,官方说明如下:
- download and expand our installation tar
- copy the phoenix server jar that is compatible with your HBase installation into the lib directory of every region server
- restart the region servers
- add the phoenix client jar to the classpath of your HBase client
- download and setup SQuirrel as your SQL client so you can issue adhoc SQL against your HBase cluster
1.1 下载并解压
官方针对 Apache 版本和 CDH
版本的 HBase
均提供了安装包,按需下载即可。官方下载地址: http://phoenix.apache.org/download.html
# 下载
wget http://mirror.bit.edu.cn/apache/phoenix/apache-phoenix-4.14.0-cdh5.14.2/bin/apache-phoenix-4.14.0-cdh5.14.2-bin.tar.gz
# 解压
tar tar apache-phoenix-4.14.0-cdh5.14.2-bin.tar.gz
1.2 拷贝Jar包
按照官方文档的说明,需要将 phoenix server jar
添加到所有 Region Servers
的安装目录的 lib
目录下。
这里由于我搭建的是 HBase
伪集群,所以只需要拷贝到当前机器的 HBase
的 lib
目录下。如果是真实集群,则使用 scp
命令分发到所有 Region Servers
机器上。
cp /usr/app/apache-phoenix-4.14.0-cdh5.14.2-bin/phoenix-4.14.0-cdh5.14.2-server.jar /usr/app/hbase-1.2.0-cdh5.15.2/lib
1.3 重启 Region Servers
# 停止Hbase
stop-hbase.sh
# 启动Hbase
start-hbase.sh
1.4 启动Phoenix
在 Phoenix
解压目录下的 bin
目录下执行如下命令,需要指定 Zookeeper
的地址:
如果 HBase
采用 Standalone
模式或者伪集群模式搭建,则默认采用内置的 Zookeeper
服务,端口为 2181
;
如果是 HBase
是集群模式并采用外置的 Zookeeper
集群,则按照自己的实际情况进行指定。
# ./sqlline.py hadoop001:2181
1.5 启动结果
启动后则进入了 Phoenix
交互式 SQL 命令行,可以使用 !table
或 !tables
查看当前所有表的信息
2.1 创建表
CREATE TABLE IF NOT EXISTS us_population (
state CHAR(2) NOT NULL,
city VARCHAR NOT NULL,
population BIGINT
CONSTRAINT my_pk PRIMARY KEY (state, city));
新建的表会按照特定的规则转换为 HBase 上的表,关于表的信息,可以通过 Hbase Web UI 进行查看:
2.2 插入数据
Phoenix
中插入数据采用的是 UPSERT
而不是 INSERT
,因为 Phoenix
并没有更新操作,插入相同主键的数据就视为更新,所以 UPSERT
就相当于 UPDATE
+INSERT
UPSERT INTO us_population VALUES('NY','New York',8143197);
UPSERT INTO us_population VALUES('CA','Los Angeles',3844829);
UPSERT INTO us_population VALUES('IL','Chicago',2842518);
UPSERT INTO us_population VALUES('TX','Houston',2016582);
UPSERT INTO us_population VALUES('PA','Philadelphia',1463281);
UPSERT INTO us_population VALUES('AZ','Phoenix',1461575);
UPSERT INTO us_population VALUES('TX','San Antonio',1256509);
UPSERT INTO us_population VALUES('CA','San Diego',1255540);
UPSERT INTO us_population VALUES('TX','Dallas',1213825);
UPSERT INTO us_population VALUES('CA','San Jose',912332);
2.3 修改数据
## 插入主键相同的数据就视为更新
UPSERT INTO us_population VALUES('NY','New York',999999);
DELETE FROM us_population WHERE city='Dallas';
SELECT state as "州",count(city) as "市",sum(population) as "热度" FROM us_population GROUP BY state ORDER BY sum(population) DESC;
!quit
2.7 扩展
从上面的操作中可以看出,Phoenix
支持大多数标准的 SQL 语法。关于 Phoenix
支持的语法、数据类型、函数、序列等详细信息,因为涉及内容很多,可以参考其官方文档,官方文档上有详细的说明:
语法 (Grammar)
函数 (Functions)
数据类型 (Datatypes)
序列 (Sequences)
联结查询 (Joins)
参考资料:
1.Phoenix 综述
2.使用phoenix踩的坑与设计思考