HBase 是一个开源的非关系型分布式数据库(NoSQL),它使用 Java 语言实现了 Google 的 BigTable,运行于 HDFS 文件系统之上,为 Hadoop 提供类似于 BigTable 规模的服务,可以对稀疏文件提供极高的容错率。
概述
就像 HDFS 和 MapReduce 是 Google 的 GFS 和 MapReduce 的实现,HBase 是 Google BigTable 的开源 Java 版本,它建立在 HDFS 之上,提供高可靠性、高性能、列存储、可伸缩、实时读写 NoSQL 的非关系型数据库系统。HBase 介于 NoSQL 和 RDBMS 之间,仅能通过行键(row key)和行键的 range 来检索数据,仅支持单行事务(可通过 Hive 来实现多表 join 等复杂操作),主要用来存储结构化和半结构化的松散数据。
HBase 中的表一般有这样的特点:
- 大:一个表可以有上十亿行,上百万列;
- 面向列:面向列(族)的存储和权限控制,列(族)独立检索;
- 稀疏:对于为空(null)的列,并不占用存储空间,因此表可以设计的非常稀疏。
HBase表的组成
表模型
Table:表,由多个行组成,表名作为路径的一部分存储在文件系统中
ROW:行,由多个列族组成,为逻辑上的行
RowKey:行键,每一行根据 RowKey 进行字典排序,因此行键的设计非常重要
Column Family:列族/列簇,由一个或多个列组成,在磁盘上是按列族存储数据的,因此在创建表的时候就必须指定列族
Column:列,由列族加上列的标识组成,一般是列簇:列标识
,可以动态定义,创建表的时候无需指定列标识
Column Qualifier:列标识,用来具体描述每一列
Timestamp:时间戳,用来记录 HBase 数据的版本,每次生成或修改数据时都保存一个时间戳
Cell:单元,用来保存具体的数据,不记录原本的数据类型,全部以byte[]
类型存储,因此使用时需要显示转换为原来的类型,由{row key, column( =<family> + <label>), version}
进行唯一标识
HBase 表中最基本的单位是列(column),若干列形成一行(row),并由唯一的行键(row key)来确定存储;一个表中有若干行,这些行按照行键的字典排序进行存储;HBase 中存储的数据可以保留多个版本,原因是每一个单元格(cell)中存储了不同的值。
列族
若干列构成一个列族(column family),这不仅有助于构建数据的语义边界,还有助于给它们设置某些特性(比如压缩),或者指示存储在内存中。一个列族的所有列存储在同一个底层的文件中,这个文件叫作 HFile
。列族需要在创建表时定义好,并且不能修改得太频繁,由于当前实现上的缺陷导致列族数量也不能太多(几十个或更少)。列族的名称必须由可打印字符组成。
列限定符
列的常见引用格式为 family:qualifier
,family
为列族,qualifier
为列(限定符)。列名可以是任意字节数组,并且数量没有限制(可以有数百万个列),列值也没有类型和长度的限制。
单元格
https://hbase.apache.org/apidocs/org/apache/hadoop/hbase/Cell.html
由行键、列族、列限定符、数据和时间戳组合起来叫做一个单元格( Cell)。这里的行键、列族、列修饰符和时间戳其实可以看作是定位属性(类似坐标),最终确定了一个数据。下图中的一行相等于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/ |
修改配置文件
- node01 修改文件
hbase-env.sh
:
1 | # export JAVA_HOME=/usr/java/jdk1.6.0/ |
- node01 修改配置文件
hbase-site.xml
:
注:0.98之前版本没有.port
配置,默认端口为60000
1 | <configuration> |
- node01 修改配置文件
regionservers
:
1 | - localhost |
- node01 创建
back-masters
文件,实现HMaster
高可用:
1 | # vim backup-masters |
分发
分发 node01 上的 HBase 到其他节点:
1 | scp -r hbase-1.2.0-cdh5.14.0/ node02:$PWD |
创建软链接
因为 HBase 需要读取 Hadoop 的 core-site.xml
以及 hdfs-site.xml
中的配置文件信息,所以我们三台机器都要执行以下命令创建软链接:
1 | 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 |
添加环境变量
三台机器都要执行以下命令添加HBASE_HOME
的环境变量:
1 | # vim /etc/profile |
启动
启动集群
node01 执行以下命令进行启动 HBase 集群:
1 | bin/start-hbase.sh |
注:HBase启动的时候会产生警告,这是因为JDK版本导致的,如果服务器使用的是 JDK8
就会产生这样的警告,不影响正常运行。可以通过注释掉所有机器中 hbase-env.sh
文件中的 HBASE_MASTER_OPTS
和 HBASE_REGIONSERVER_OPTS
两个配置来解决这个问题。
启动单个节点
也可以执行以下命令单节点进行启动:
1 | # 启动HMaster |
为了解决 HMaster 单点故障问题,可以在 node02 上启动 HMaster 节点的进程,以实现 HMaster 的高可用。
访问监控页面
浏览器页面访问:http://node01:60010/master-status
Shell
HBase 的常用 shell 操作。
进入客户端
1 | # /export/servers/hbase-1.2.0-cdh5.14.0/bin/hbase shell |
表模型
Table:表,由多个行组成,表名作为路径的一部分存储在文件系统中
ROW:行,由多个列族组成,为逻辑上的行
RowKey:行键,每一行根据 RowKey 进行字典排序,因此行键的设计非常重要
Column Family:列族/列簇,由一个或多个列组成,在磁盘上是按列族存储数据的,因此在创建表的时候就必须指定列族
Column:列,由列族加上列的标识组成,一般是列簇:列标识
,可以动态定义,创建表的时候无需指定列标识
Column Qualifier:列标识,用来具体描述每一列
Timestamp:时间戳,用来记录 HBase 数据的版本,每次生成或修改数据时都保存一个时间戳
Cell:单元,用来保存具体的数据,不记录原本的数据类型,全部以byte[]
类型存储,因此使用时需要显示转换为原来的类型,由{row key, column( =<family> + <label>), version}
进行唯一标识
查看与创建表
查看数据库中有哪些表:
1 | -- list |
创建表,同时创建列族:
1 | --创建user表,包含info、data两个列族 |
添加数据
添加/更新数据到指定表中的指定列族中,同时创建列、RowKey 和值:
1 | -- 向user表中插入信息,row key为rk0001,列族info中添加name列标示符,值为zhangsan |
查询数据
直接查询
通过RowKey进行直接查询
1 | #获取user表中RowKey为rk0001的所有信息 |
查看RowKey下面的某个列族的信息
1 | #获取user表中row key为rk0001,info列族的所有信息 |
查看RowKey指定列族指定字段的值
1 | #获取user表中row key为rk0001,info列族的name、age列标示符的信息 |
查看RowKey指定多个列族的信息
1 | #获取user表中row key为rk0001,info、data列族的信息 |
指定RowKey与列值查询
1 | #获取user表中row key为rk0001,cell的值为zhangsan的信息 |
指定RowKey与列值模糊查询
1 | #获取user表中row key为rk0001,列标示符中含有a的信息 |
扫描
全表扫描
1 | #查询user表中的所有信息 |
限制扫描数量
1 | #扫描user表中10条记录 |
列族查询
1 | #查询user表中列族为info的信息 |
多列族查询
1 | #查询user表中列族为info和data的信息 |
指定列族与某个列名查询
1 | #查询user表中列族为info、列标示符为name的信息 |
指定列族与列名以及限定版本查询
1 | #查询user表中列族为info、列标示符为name的信息,并且版本最新的5个 |
指定多个列族与按照数据值模糊查询
1 | #查询user表中列族为info和data且列标示符中含有a字符的信息 |
RowKey的范围值查询
1 | #查询user表中列族为info,rk范围是[rk0001, rk0003)的数据 |
指定RowKey模糊查询
1 | #查询user表中row key以rk字符开头的 |
指定数据范围值查询
1 | #查询user表中指定范围的数据 |
Java
使用 Java 代码实现 HBase 数据库当中的数据增删改查的操作。
导入依赖
1 | <repositories> |