0%

HBase快速上手

HBase头图

HBase是一个开源的非关系型分布式数据库(NoSQL),它参考了谷歌的BigTable建模,实现的编程语言为 Java。它是Apache软件基金会的Hadoop项目的一部分,运行于HDFS文件系统之上,为 Hadoop 提供类似于BigTable 规模的服务。因此,它可以对稀疏文件提供极高的容错率。


概述

HBase 是 BigTable 的开源 Java 版本。建立在 HDFS 之上,提供高可靠性、高性能、列存储、可伸缩、实时读写 NoSQL 的非关系型数据库系统。它介于 NoSQL 和 RDBMS 之间,仅能通过主键(row key)和主键的 range 来检索数据,仅支持单行事务(可通过 Hive 来实现多表 join 等复杂操作),主要用来存储结构化和半结构化的松散数据。

HBase 中的表一般有这样的特点:

  • 大:一个表可以有上十亿行,上百万列
  • 面向列:面向列(族)的存储和权限控制,列(族)独立检索
  • 稀疏:对于为空(null)的列,并不占用存储空间,因此表可以设计的非常稀疏

基础架构

HBase基础架构

HMaster 为主节点,HRegionServer 为从节点。HBase 强依赖于 Zookeeper 和 Hadoop,启动 HBase 之前一定要确保 Zookeeper 和 Hadoop 启动成功并正常运行。

HMaster

  • 为 HRegionServer 分配 Region
  • 负责 HRegionServer 的负载均衡
  • 处理 HRegionServer 故障转移,重新分配其中的 Region
  • 处理 Region 的分配或移除
  • 处理元数据的变更
  • 回收 HDFS 上的垃圾文件
  • 通过 Zookeeper 发布自己的位置给 Client

HRegionServer

  • 负责存储 HBase 的实际数据
  • 维护 HMaster 分配给它的 Region
  • 维护 HLog
  • 存储到 HDFS
  • 切分过大的 HFile

Hlog:HBase 读写数据的时候,数据会在内存中保留,满足条件(如 128 MB 或 1 小时等)后再写进磁盘生成 HFile 文件。为了避免数据在内存中丢失,HBase 使用 WAL 机制(Write-Ahead logfile),在数据写入到内存之前先生成日志文件,这样在系统出现故障的时候,可以通过日志文件重建数据,避免数据丢失。

Region一个 Region 对应一张 HBase 表(或表的分片),数据在磁盘上以 HFile 文件进行存储。单个 HFile 文件如果过大(10 GB),会被 HRegionServer 切分为两个,相应的 Region 也会被切分成两个 Region 分片。一个 HRegionServer 中可以有多个不同的 Region。

Store一个 Store 对应 HBase 表中的一个列族(Column Family)。因为一张表可以有多个列族,所以一个 Region 中可以有多个 Store。Store 又分为两部分:

  • MemoryStore:内存存储,用来保存当前的数据操作,默认大小为 128 MB。在记录 Hlog 日志之后,数据便写入 MemoryStore。
  • StoreFile:文件存储,每当 MemoryStore 存储的数据达到阈值(如 128 MB 或 1 小时等)便写入到磁盘,生成一个 StoreFile(HFile 文件)。大量的 HFile 小文件会通过 Compact 机制合并成一个 HFile 大文件,再写入 HDFS。

HDFS

负责存储 HFile 文件,单个 HFile 文件达到 10 GB 后会被一分为二。

Zookeeper

  • 保证任何时候,集群中只有一个 HMaster 处于 Active
  • 存储所有 Region 的寻址入口
  • 实时监控 HRegionServer 的状态,将上下线信息实时通知给 HMaster
  • 存储 HBase 的 schema,包括表和表中的列族

Client

包含访问 HBase 的接口,Client 维护着一些 cache 来加快对 HBase 的访问,如 Regione 的位置信息

安装

HBase强依赖 Zookeeper和 Hadoop,安装 HBase 之前一定要保证 Zookeeper 和 Hadoop 启动成功并正常运行。

下载安装

CDH版本的软件包地址: http://archive.cloudera.com/cdh5/cdh/5/

HBase的下载地址: http://archive.cloudera.com/cdh5/cdh/5/hbase-1.2.0-cdh5.14.0.tar.gz

安装 HBase:

1
tar -zxvf /export/softwares/hbase-1.2.0-cdh5.14.0.tar.gz -C /export/servers/

修改配置文件

  1. node01 修改文件hbase-env.sh
/export/servers/hbase-1.2.0-cdh5.14.0/conf/hbase-env.sh
1
2
3
4
5
# export JAVA_HOME=/usr/java/jdk1.6.0/
+ export JAVA_HOME=/usr/java/jdk1.8.0_211/

# export HBASE_MANAGES_ZK=true
+ export HBASE_MANAGES_ZK=false
  1. node01 修改配置文件hbase-site.xml

注:0.98之前版本没有.port配置,默认端口为60000

/export/servers/hbase-1.2.0-cdh5.14.0/conf/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
<configuration>
<property>
<name>hbase.rootdir</name>
<value>hdfs://node01:8020/hbase</value>
</property>

<property>
<name>hbase.cluster.distributed</name>
<value>true</value>
</property>

<property>
<name>hbase.master.port</name>
<value>16000</value>
</property>

<property>
<name>hbase.zookeeper.quorum</name>
<value>node01:2181,node02:2181,node03:2181</value>
</property>

<property>
<name>hbase.zookeeper.property.dataDir</name>
<value>/export/servers/zookeeper-3.4.5-cdh5.14.0/zkdatas</value>
</property>
</configuration>
  1. node01 修改配置文件regionservers
/export/servers/hbase-1.2.0-cdh5.14.0/conf/regionservers
1
2
3
4
- localhost
+ node01
+ node02
+ node03
  1. node01 创建back-masters文件,实现HMaster高可用:
/export/servers/hbase-1.2.0-cdh5.14.0/conf/
1
2
# vim backup-masters
node02

分发

分发 node01 上的 HBase 到其他节点:

/export/servers/
1
2
scp -r hbase-1.2.0-cdh5.14.0/ node02:$PWD
scp -r hbase-1.2.0-cdh5.14.0/ node03:$PWD

创建软链接

因为 HBase 需要读取 Hadoop 的 core-site.xml 以及 hdfs-site.xml 中的配置文件信息,所以我们三台机器都要执行以下命令创建软链接:

1
2
ln -s /export/servers/hadoop-2.6.0-cdh5.14.0/etc/hadoop/core-site.xml /export/servers/hbase-1.2.0-cdh5.14.0/conf/core-site.xml
ln -s /export/servers/hadoop-2.6.0-cdh5.14.0/etc/hadoop/hdfs-site.xml /export/servers/hbase-1.2.0-cdh5.14.0/conf/hdfs-site.xml

添加环境变量

三台机器都要执行以下命令添加HBASE_HOME的环境变量:

1
2
3
# vim /etc/profile
export HBASE_HOME=/export/servers/hbase-1.2.0-cdh5.14.0
export PATH=:$HBASE_HOME/bin:$PATH

启动

启动集群

node01 执行以下命令进行启动 HBase 集群:

/export/servers/hbase-1.2.0-cdh5.14.0/
1
bin/start-hbase.sh

启动HBase

注:HBase启动的时候会产生警告,这是因为JDK版本导致的,如果服务器使用的是 JDK8 就会产生这样的警告,不影响正常运行。可以通过注释掉所有机器中 hbase-env.sh 文件中的 HBASE_MASTER_OPTSHBASE_REGIONSERVER_OPTS 两个配置来解决这个问题。

启动单个节点

也可以执行以下命令单节点进行启动:

/export/servers/hbase-1.2.0-cdh5.14.0/
1
2
3
4
5
# 启动HMaster
# bin/hbase-daemon.sh start master

# 启动HRegionServer
# bin/hbase-daemon.sh start regionserver

为了解决 HMaster 单点故障问题,可以在 node02 上启动 HMaster 节点的进程,以实现 HMaster 的高可用。

访问监控页面

浏览器页面访问:http://node01:60010/master-status

HBase页面访问

Shell

HBase 的常用 shell 操作。

进入客户端

1
2
3
4
5
# /export/servers/hbase-1.2.0-cdh5.14.0/bin/hbase shell
hbase(main):001:0>

#查看帮助
hbase(main):001:0> help

表模型

HBase表模型

Table:表,由多个行组成,表名作为路径的一部分存储在文件系统中
ROW:行,由多个列族组成,为逻辑上的行
RowKey:行键,每一行根据 RowKey 进行字典排序,因此行键的设计非常重要
Column Family:列族/列簇,由一个或多个列组成,在磁盘上是按列族存储数据的,因此在创建表的时候就必须指定列族
Column:列,由列族加上列的标识组成,一般是列簇:列标识,可以动态定义,创建表的时候无需指定列标识
Column Qualifier:列标识,用来具体描述每一列
Timestamp:时间戳,用来记录 HBase 数据的版本,每次生成或修改数据时都保存一个时间戳
Cell:单元,用来保存具体的数据,不记录原本的数据类型,全部以byte[]类型存储,因此使用时需要显示转换为原来的类型,由{row key, column( =<family> + <label>), version}进行唯一标识

查看与创建表

查看数据库中有哪些表:

1
list

创建表,同时创建列族:

1
2
3
4
5
--创建user表,包含info、data两个列族
create 'user', 'info', 'data'

--在创建user表时指定info列族中的数据保存3个版本
create 'user', {NAME => 'info', VERSIONS => '3'},{NAME => 'data'}

添加数据

添加/更新数据到指定表中的指定列族中,同时创建列、RowKey 和值:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
#向user表中插入信息,row key为rk0001,列族info中添加name列标示符,值为zhangsan
put 'user', 'rk0001', 'info:name', 'zhangsan'

#向user表中插入信息,row key为rk0001,列族info中添加gender列标示符,值为female
put 'user', 'rk0001', 'info:gender', 'female'

#向user表中插入信息,row key为rk0001,列族info中添加age列标示符,值为20
put 'user', 'rk0001', 'info:age', 20

#向user表中插入信息,row key为rk0001,列族data中添加pic列标示符,值为picture
put 'user', 'rk0001', 'data:pic', 'picture'

#继续插入一批数据
put 'user', 'rk0002', 'info:name', 'fanbingbing'
put 'user', 'rk0002', 'info:gender', 'female'
put 'user', 'rk0002', 'info:nationality', '中国'

查询数据

直接查询

通过RowKey进行直接查询

1
2
#获取user表中RowKey为rk0001的所有信息
get 'user', 'rk0001'

查看RowKey下面的某个列族的信息

1
2
#获取user表中row key为rk0001,info列族的所有信息
get 'user', 'rk0001', 'info'

查看RowKey指定列族指定字段的值

1
2
#获取user表中row key为rk0001,info列族的name、age列标示符的信息
get 'user', 'rk0001', 'info:name', 'info:age'

查看RowKey指定多个列族的信息

1
2
3
4
5
6
#获取user表中row key为rk0001,info、data列族的信息
get 'user', 'rk0001', 'info', 'data'

get 'user', 'rk0001', {COLUMN => ['info', 'data']}

get 'user', 'rk0001', {COLUMN => ['info:name', 'data:pic']}

指定RowKey与列值查询

1
2
#获取user表中row key为rk0001,cell的值为zhangsan的信息
get 'user', 'rk0001', {FILTER => "ValueFilter(=, 'binary:zhangsan')"}

指定RowKey与列值模糊查询

1
2
3
#获取user表中row key为rk0001,列标示符中含有a的信息
get 'user', 'rk0001', {FILTER => "(QualifierFilter(=,'substring:a'))"}
get 'user', 'rk0002', {FILTER => "ValueFilter(=, 'binary:中国')"}

扫描

全表扫描

1
2
#查询user表中的所有信息
scan 'user'

列族查询

1
2
3
4
#查询user表中列族为info的信息
scan 'user', {COLUMNS => 'info'}
scan 'user', {COLUMNS => 'info', RAW => true, VERSIONS => 5}
scan 'user', {COLUMNS => 'info', RAW => true, VERSIONS => 3}

多列族查询

1
2
3
#查询user表中列族为info和data的信息
scan 'user', {COLUMNS => ['info', 'data']}
scan 'user', {COLUMNS => ['info:name', 'data:pic']}

指定列族与某个列名查询

1
2
#查询user表中列族为info、列标示符为name的信息
scan 'user', {COLUMNS => 'info:name'}

指定列族与列名以及限定版本查询

1
2
#查询user表中列族为info、列标示符为name的信息,并且版本最新的5个
scan 'user', {COLUMNS => 'info:name', VERSIONS => 5}

指定多个列族与按照数据值模糊查询

1
2
#查询user表中列族为info和data且列标示符中含有a字符的信息
scan 'user', {COLUMNS => ['info', 'data'], FILTER => "(QualifierFilter(=,'substring:a'))"}

RowKey的范围值查询

1
2
#查询user表中列族为info,rk范围是[rk0001, rk0003)的数据
scan 'user', {COLUMNS => 'info', STARTROW => 'rk0001', ENDROW => 'rk0003'}

指定RowKey模糊查询

1
2
#查询user表中row key以rk字符开头的
scan 'user',{FILTER=>"PrefixFilter('rk')"}

指定数据范围值查询

1
2
#查询user表中指定范围的数据
scan 'user', {TIMERANGE => [1392368783980, 1392380169184]}

Java

使用 Java 代码实现 HBase 数据库当中的数据增删改查的操作。

导入依赖

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
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
<repositories>
<repository>
<id>cloudera</id>
<url>https://repository.cloudera.com/artifactory/cloudera-repos/</url>
</repository>
</repositories>

<dependencies>
<dependency>
<groupId>org.apache.hadoop</groupId>
<artifactId>hadoop-client</artifactId>
<version>2.6.0-mr1-cdh5.14.0</version>
</dependency>
<dependency>
<groupId>org.apache.hbase</groupId>
<artifactId>hbase-client</artifactId>
<version>1.2.0-cdh5.14.0</version>
</dependency>
<dependency>
<groupId>org.apache.hbase</groupId>
<artifactId>hbase-server</artifactId>
<version>1.2.0-cdh5.14.0</version>
</dependency>

<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<!--<scope>test</scope>-->
</dependency>
<dependency>
<groupId>org.testng</groupId>
<artifactId>testng</artifactId>
<version>6.14.3</version>
<!--<scope>test</scope>-->
</dependency>
</dependencies>

<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.0</version>
<configuration>
<source>1.8</source>
<target>1.8</target>
<encoding>UTF-8</encoding>
<!--<verbal>true</verbal>-->
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-shade-plugin</artifactId>
<version>2.2</version>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>shade</goal>
</goals>
<configuration>
<filters>
<filter>
<artifact>*:*</artifact>
<excludes>
<exclude>META-INF/*.SF</exclude>
<exclude>META-INF/*.DSA</exclude>
<exclude>META-INF/*/RSA</exclude>
</excludes>
</filter>
</filters>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
  • 本文作者: SANNAHA
  • 本文链接: https://sannaha.moe/HBase/
  • 版权声明: 本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!