无论是 NoSQL,还是大数据领域,HBase 都是非常"炙热"的一门数据库。

本文将对 HBase 做一些基础性的介绍,旨在入门。

一、简介

HBase 是一个开源的、面向列的非关系型分布式数据库,目前是Hadoop体系中非常关键的一部分。

在最初,HBase是基于谷歌的 BigTable 原型实现的,许多技术来自于Fay Chang在2006年所撰写的Google论文"BigTable"。与 BigTable基于Google文件系统(File System)一样,HBase则是基于HDFS(Hadoop的分布式文件系统)之上而开发的。

HBase 采用 Java 语言实现,在其内部实现了BigTable论文提到的一些压缩算法、内存操作和布隆过滤器等,这些能力使得HBase 在海量数据存储、高性能读写场景中得到了大量应用,如 Facebook 在 2010年11 月开始便一直选用 HBase来作为消息平台的存储层技术。

HBase 以 Apache License Version 2.0开源,这是一种对商业应用友好的协议,同时该项目当前也是Apache软件基金会的顶级项目之一。

有什么特性

  • 基于列式存储模型,对于数据实现了高度压缩,节省存储成本
  • 采用 LSM 机制而不是B(+)树,这使得HBase非常适合海量数据实时写入的场景
  • 高可靠,一个数据会包含多个副本(默认是3副本),这得益于HDFS的复制能力,由RegionServer提供自动故障转移的功能
  • 高扩展,支持分片扩展能力(基于Region),可实现自动、数据均衡
  • 强一致性读写,数据的读写都针对主Region上进行,属于CP型的系统
  • 易操作,HBase提供了Java API、RestAPI/Thrift API等接口
  • 查询优化,采用Block Cache 和 布隆过滤器来支持海量数据的快速查找

与RDBMS的区别

对于传统 RDBMS 来说,支持 ACID 事务是数据库的基本能力,而 HBase 则使用行级锁来保证写操作的原子性,但是不支持多行写操作的事务性,这主要是从灵活性和扩展性上做出的权衡。

ACID 要素包含 原子性(Atomicity)、一致性(Consistency)、隔离性(Isolation)以及持久性(Durability)

总体来说, HBase 与传统关系数据库的区别,如下表所示:

特性 HBase RDBMS
硬件架构 类似于 Hadoop 的分布式集群,硬件成本低廉 传统的多核系统,硬件成本昂贵
容错性 由软件架构实现,由于由多个节点组成,所以不担心一点或几点宕机 一般需要额外硬件设备实现 HA 机制
数据库大小 PB GB、TB
数据排布方式 稀疏的、分布的多维的 Map 以行和列组织
数据类型 Bytes 丰富的数据类型
事物支持 ACID 只支持单个 Row 级别 全面的 ACID 支持,对 Row 和表
查询语言 只支持 Java API (除非与其他框架一起使用,如 Phoenix、Hive) SQL
索引 只支持 Row-key,除非与其他技术一起应用,如 Phoenix、Hive 支持
吞吐量 百万查询/每秒 数千查询/每秒

二、数据模型

下面,我们以关系型数据库的一个数据表来演示 HBase 的不同之处。 先来看下面这张表:

ID 设备名 状态 时间戳
1 空调 打开 20190712 10:05:01
2 电视机 关闭 20190712 10:05:08

这里记录的是一些家庭设备上报的状态数据(DeviceState),其中包括设备名、状态、时间戳这些字段。

在 HBase 中,数据是按照列族(Column Family,简称CF)来存储的,也就是说对于不同的列会被分开存储到不同的文件。

那么对于上面的状态数据表来说,在HBase中会被存储为两份:

列族1. 设备名

Row-Key CF:Column-Key Timestamp Cell Value
1 DeviceState:设备名 20190712 10:05:01 空调
2 DeviceState:设备名 20190712 10:05:08 电视机

列族2. 状态

Row-Key CF:Column-Key Timestamp Cell Value
1 DeviceState:状态 20190712 10:05:01 打开
2 DeviceState:状态 20190712 10:05:08 关闭

这里Row-key是唯一定位数据行的ID字段,而Row-key 加上 CF、Column-Key,再加上一个时间戳才可以定位到一个单元格数据。

其中时间戳用来表示数据行的版本, 在HBase中默认会有 3 个时间戳的版本数据,这意味着对同一条数据(同一个Rowkey关联的数据)进行写入时,最多可以保存3个版本。

在查询某一行的数据时,HBase需要同时从两个列族(文件)中进行查找,最终将结果合并后返回给客户端。 由此可见如果列族太多,则会影响读取的性能,在设计时就需要做一些权衡。

由此可见,HBase的使用方式与关系型数据库是大不相同的,在使用 HBase 时需要抛弃许多关系型数据库的思维及做法,比如强类型、二级索引、表连接、触发器等等。

然而 HBase 的灵活性及高度可伸缩性却是传统 RDBMS 无法比拟的。

三、安装HBase

单机环境安装

  1. 准备JDK环境

确保环境上JDK已经装好,可执行java -version确认:

host:/home/hbase # java -version
openjdk version "1.8.0_201"
OpenJDK Runtime Environment (build 1.8.0_201-Huawei_JDK_V100R001C00SPC060B003-b10)
OpenJDK 64-Bit Server VM (build 25.201-b10, mixed mode)
  1. 下载软件

官网的下载地址页面:

http://archive.apache.org/dist/hbase/

选择合适的版本,比如1.4.10。 下载后解压:

wget http://archive.apache.org/dist/hbase/2.1.5/hbase-2.1.5-bin.tar.gz
tar -xzvf hbase-2.1.5-bin.tar.gz
mkdir -p /opt/local
mv hbase-2.1.5 /opt/local/hbase

配置HBase执行命令路径:

export HBASE_HOME=/opt/local/hbase
export PATH=$PATH:$HBASE_HOME/bin
  1. 配置软件

vim conf/hbase-env.sh

#JDK安装目录
export JAVA_HOME=/usr/local/jre1.8.0_201
#配置hbase自己管理zookeeper
export HBASE_MANAGES_ZK=true

vim conf/hbase-site.xml

<configuration>

  <!-- zookeeper端口  -->
<property>
<name>hbase.zookeeper.property.clientPort</name>
<value>2182</value>
</property> <!-- HBase 数据存储目录 -->
<property>
<name>hbase.rootdir</name>
<value>file:///opt/local/hbase/data</value>
</property> <!-- 用于指定 ZooKeeper 数据存储目录 -->
<property>
<name>hbase.zookeeper.property.dataDir</name>
<value>/opt/local/hbase/data/zookeeper</value>
</property> <!-- 用于指定临时数据存储目录 -->
<property>
<name>hbase.tmp.dir</name>
<value>/opt/local/hbase/temp/hbase-${user.name}</value>
</property>
</configuration>

其中 hbase.rootdir 和 hbase.zookeeper.property.dataDir 都用来指定数据存放的目录,默认情况下hbase会使用/tmp目录,这显然是不合适的。

配置了这两个路径之后,hbase会自动创建相应的目录。

关于更多的参数设定可参考这里

  1. 启动软件
start-hbase.sh

此时查看 logs/hbase-root-master-host-xxx.log,如下:

2019-07-11 07:37:23,654 INFO  [localhost:33539.activeMasterManager] hbase.MetaMigrationConvertingToPB: hbase:meta doesn't have any entries to update.
2019-07-11 07:37:23,654 INFO [localhost:33539.activeMasterManager] hbase.MetaMigrationConvertingToPB: META already up-to date with PB serialization
2019-07-11 07:37:23,664 INFO [localhost:33539.activeMasterManager] master.AssignmentManager: Clean cluster startup. Assigning user regions
2019-07-11 07:37:23,665 INFO [localhost:33539.activeMasterManager] master.AssignmentManager: Joined the cluster in 11ms, failover=false
2019-07-11 07:37:23,672 INFO [localhost:33539.activeMasterManager] master.TableNamespaceManager: Namespace table not found. Creating...

检查进程情况,发现进程已经启动

ps -ef |grep hadoop
root 11049 11032 2 07:37 pts/1 00:00:20 /usr/local/jre1.8.0_201/bin/java -Dproc_master -XX:OnOutOfMemoryError=kill -9 %p -XX:+UseConcMarkSweepGC -XX:PermSize=128m -XX:MaxPermSize=128m -XX:ReservedCodeCacheSize=256m -Dhbase.log.dir=/opt/local/hbase/logs -Dhbase.log.file=hbase-root-master-host-192-168-138-148.log -Dhbase.home.dir=/opt/local/hbase -Dhbase.id.str=root -Dhbase.root.logger=INFO,RFA -Dhbase.security.logger=INFO,RFAS org.apache.hadoop.hbase.master.HMaster start
root 18907 30747 0 07:50 pts/1 00:00:00 grep --color=auto hadoop

通过JPS(JDK自带的检查工具) 可以看到当前启动的Java进程:

# jps
5701 Jps
4826 HMaster
1311 jar

查看 data目录,发现生成了对应的文件:

host:/opt/local/hbase/data # ls -lh .
total 36K
drwx------. 4 root root 4.0K Jul 11 08:08 data
drwx------. 4 root root 4.0K Jul 11 08:08 hbase
-rw-r--r--. 1 root root 42 Jul 11 08:08 hbase.id
-rw-r--r--. 1 root root 7 Jul 11 08:08 hbase.version
drwx------. 2 root root 4.0K Jul 11 08:08 MasterProcWALs
drwx------. 2 root root 4.0K Jul 11 08:08 oldWALs
drwx------. 3 root root 4.0K Jul 11 08:08 .tmp
drwx------. 3 root root 4.0K Jul 11 08:08 WALs
drwx------. 3 root root 4.0K Jul 11 08:08 zookeeper

关于运行模式

HBase启动时默认会使用单机模式,此时 Zookeeper和 HMaster/RegionServer 会运行在同一个JVM中。

以standalone模式启动的HBase会包含一个HMaster、RegionServer、Zookeeper实例,此时 HBase 会直接使用本地文件系统而不是HDFS。

通过将 conf/hbase-site.xml中的 hbase.cluster.distributed 配置为true,就是集群模式了。

在这个模式下,你可以使用分布式环境进行部署,或者是"伪分布式"的多进程环境。

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

需要注意的是,如果以standalone启动的话,HMaster、RegionServer端口都是随机的,无法通过配置文件指定。

四、基本使用

打开HBase Shell

hbase shell

执行status命令

Version 2.1.5, r76ab087819fe82ccf6f531096e18ad1bed079651, Wed Jun  5 16:48:11 PDT 2019

hbase(main):001:0> status
1 active master, 0 backup masters, 1 servers, 0 dead, 2.0000 average load

这表示有一个Master在运行,一个RegionServer,每个RegionServer包含2个Region。

表操作

  • 创建DeviceState表
hbase(main):002:0> create "DeviceState", "name:c1", "state:c2"

=> Hbase::Table - DeviceState

此时,已经创建了一个DeviceState表,包含name(设备名称)、state(状态)两个列。

查看表信息:

hbase(main):003:0> list
TABLE
DeviceState
1 row(s) in 0.0090 seconds => ["DeviceState"] hbase(main):003:0> describe "DeviceState"
Table DeviceState is ENABLED
DeviceState
COLUMN FAMILIES DESCRIPTION
{NAME => 'name', BLOOMFILTER => 'ROW', VERSIONS => '1', IN_MEMORY => 'false', KEEP_DELETED_CELLS => 'FALSE', DATA_BLOCK_ENCODING => 'NONE', TTL => 'FOREVER', COMPRESSIO
N => 'NONE', MIN_VERSIONS => '0', BLOCKCACHE => 'true', BLOCKSIZE => '65536', REPLICATION_SCOPE => '0'}
{NAME => 'state', BLOOMFILTER => 'ROW', VERSIONS => '1', IN_MEMORY => 'false', KEEP_DELETED_CELLS => 'FALSE', DATA_BLOCK_ENCODING => 'NONE', TTL => 'FOREVER', COMPRESSI
ON => 'NONE', MIN_VERSIONS => '0', BLOCKCACHE => 'true', BLOCKSIZE => '65536', REPLICATION_SCOPE => '0'}
2 row(s) in 0.0870 seconds
  • 写入数据

通过下面的命令,向DeviceState写入两条记录,由于有两个列族,因此需要写入四个单元格数据:

put "DeviceState", "row1", "name", "空调"
put "DeviceState", "row1", "state", "打开"
put "DeviceState", "row2", "name", "电视机"
put "DeviceState", "row2", "state", "关闭"
  • 查询数据

查询某行、某列

hbase(main):012:0> get "DeviceState","row1"
COLUMN CELL
name: timestamp=1562834473008, value=\xE7\x94\xB5\xE8\xA7\x86\xE6\x9C\xBA
state: timestamp=1562834474630, value=\xE5\x85\xB3\xE9\x97\xAD
1 row(s) in 0.0230 seconds hbase(main):013:0> get "DeviceState","row1", "name"
COLUMN CELL
name: timestamp=1562834473008, value=\xE7\x94\xB5\xE8\xA7\x86\xE6\x9C\xBA
1 row(s) in 0.0200 seconds

扫描表

hbase(main):026:0> scan "DeviceState"
ROW COLUMN+CELL
row1 column=name:, timestamp=1562834999374, value=\xE7\xA9\xBA\xE8\xB0\x83
row1 column=state:, timestamp=1562834999421, value=\xE6\x89\x93\xE5\xBC\x80
row2 column=name:, timestamp=1562834999452, value=\xE7\x94\xB5\xE8\xA7\x86\xE6\x9C\xBA
row2 column=state:, timestamp=1562835001064, value=\xE5\x85\xB3\xE9\x97\xAD
2 row(s) in 0.0250 seconds

查询数量

hbase(main):014:0> count "DeviceState"
2 row(s) in 0.0370 seconds => 1
  • 清除数据

删除某列、某行

delete "DeviceState", "row1", "name"
0 row(s) in 0.0080 seconds hbase(main):003:0> deleteall "DeviceState", "row2"
0 row(s) in 0.1290 seconds

清空整个表数据

hbase(main):021:0> truncate "DeviceState"
Truncating 'DeviceState' table (it may take a while):
- Disabling table...
- Truncating table...
0 row(s) in 3.5060 seconds

删除表(需要先disable)

hbase(main):006:0> disable "DeviceState"
0 row(s) in 2.2690 seconds hbase(main):007:0> drop "DeviceState"
0 row(s) in 1.2880 seconds

五、FAQ

  • 启动时提示 ZK 端口监听失败:

    Could not start ZK at requested port of 2181. ZK was started at port: 2182. Aborting as clients (e.g. shell) will not be able to find this ZK quorum

原因

HBase需要启动Zookeeper,而本地的2181端口已经被启用(可能有其他Zookeeper实例)

解决办法

conf/hbase-site.xml中修改hbase.zookeeper.property.clientPort的值,将其修改为2182,:

<configuration>
<property>
<name>hbase.zookeeper.property.clientPort</name>
<value>2182</value>
</property>
</configuration>
  • 启动HBase Shell时提示java.lang.UnsatisfiedLinkError

原因

在执行hbase shell期间,JRuby会在“java.io.tmpdir”路径下创建一个临时文件,该路径的默认值为“/tmp”。如果为“/tmp”目录设置NOEXEC权限,然后hbase shell会启动失败并抛出“java.lang.UnsatisfiedLinkError”错误。

解决办法

  1. 取消/tmp的noexec权限(不推荐)
  2. 设置java.io.tmpdir变量,指向可用的路径,编辑conf/hbase-env.sh文件:
export HBASE_TMP_DIR=/opt/local/hbase/temp
export HBASE_OPTS="-XX:+UseConcMarkSweepGC -Djava.io.tmpdir=$HBASE_TMP_DIR"

参考文档

HBase 官方权威指南

https://hbase.apache.org/book.html#quickstart

HBase 单机模式搭建

https://my.oschina.net/jackieyeah/blog/712019

HBase 深入浅出

较详细介绍了HBase的由来以及特性,文中提供了HBase集群、存储机制的一些简介,非常适合入门阅读

https://www.ibm.com/developerworks/cn/analytics/library/ba-cn-bigdata-hbase/index.html

HBase 基本入门的更多相关文章

  1. HBase轻松入门之HBase架构图解析

    2018-12-13 2018-12-20 本篇文章旨在针对初学者以我本人现阶段所掌握的知识就HBase的架构图中各模块作一个概念科普.不对文章内容的“绝对.完全正确性”负责. 1.开胃小菜 关于HB ...

  2. HBase 基本入门篇

    无论是 NoSQL,还是大数据领域,HBase 都是非常”炙热”的一门数据库.本文将对 HBase 做一些基础性的介绍,旨在入门. 一.简介 HBase 是一个开源的.面向列的非关系型分布式数据库,目 ...

  3. hadoop中HBase子项目入门讲解

    HBase 是Hadoop的一个子项目,HBase采用了Google BigTable的稀疏的,面向列的数据库实现方式的理论,建立在hadoop的hdfs上,一方面里用了hdfs的高可靠性和可伸缩行, ...

  4. HBase系统入门--整体介绍

    转自:http://www.aboutyun.com/thread-8957-1-2.html 问题导读:1.HBase查询与写入哪个更好一些?2.HBase面对复杂操作能否实现?3.Region服务 ...

  5. hbase快速入门

    hbase 是什么? Apache HBase is an open-source, distributed, versioned, non-relational database modeled a ...

  6. HBase从入门到精通系列:误删数据如何抢救?

    云栖君导读:有时候我们操作数据库的时候不小心误删数据,这时候如何找回?mysql里有binlog可以帮助我们恢复数据,但是没有开binlog也没有备份就尴尬了.如果是HBase,你没有做备份误删了又如 ...

  7. HBase概念入门

    HBase简介 HBase基于Google的BigTable论文而来,是一个分布式海量列式非关系型数据库系统,可以提供大规模数据集的实时随机读写. 下面通过一个小场景认识HBase存储.同样的一个数据 ...

  8. HBase框架学习之路

    1 背景知识 1.1 解决问题 解决HDFS不支持单条记录的快速查找和更新的问题. 1.2 适用情况 存在亿万条记录的数据库,只有千万或者百万条记录使用RDBMS更加合适 确保你的应用不需要使用RDB ...

  9. HBase、Redis、MongoDB、Couchbase、LevelDB主流 NoSQL 数据库的对比

    最近小组准备启动一个 node 开源项目,从前端亲和力.大数据下的IO性能.可扩展性几点入手挑选了 NoSql 数据库,但具体使用哪一款产品还需要做一次选型. 我们最终把选项范围缩窄在 HBase.R ...

随机推荐

  1. 是可忍孰不可忍!!nodepad++作者台独分子,恶毒言论!!!

    本来用了两年这个软件吧,不带任何情感的,单纯辅助工具.直到今天,在GitHub上,发现了这个作者以及一些同党都是一群尼玛生在中国骂中国的狗币. https://github.com/notepad-p ...

  2. linux 基本操作--笔记

    linux 基本操作: pwd 显示当前目录 ll 用于查看文件和目录,即list,其参数比较多 -l 列出数据串,包含文件的属性和权限数据等 -a 列出全部文件,包含隐藏文件 -d 仅列出目录本身, ...

  3. 继承+派生+分类+钻石继承(day20)

    目录 昨日内容 面对对象编程 类 定义类时发生的事情 调用类时发生的事情 init 对象 对象查找类的属性的顺序 对象的绑定方法 python中万物皆对象 今日内容 继承 什么是继承 为什么要继承 如 ...

  4. fenby C语言 P16

    while先判断,不符合,不执行 dowhile后判断,不符合,执行一次 #include <stdio.h> int main(){ int i=1,sum=0; do{ sum=sum ...

  5. python uiautomator,比 appium 更简单的 app 测试工具

    1,场景 在 app 测试的蛮荒时代,如果要进行 app 自动化测试非常麻烦.张大胖如果想做安卓自动化测试,首先必须要学 Java.因为安卓自动化测试都绕不开 google 自己研发的自动化测试框架, ...

  6. C语言I博客作业07

    这个作业属于那个课程 C语言程序设计II 这个作业要求在哪里 https://edu.cnblogs.com/campus/zswxy/SE2019-1/homework/9931 我在这个课程的目标 ...

  7. [考试反思]1027csp-s模拟测试90:自我

    其实这套题很好. 但是这次,在T1爆炸的同时,T2和T3并没有出现能弥补的表现. 在AK仍然存在的同时,我居然连一个AC都没有. 所以最后就是一无是处的一场. 考试结束前估分:100+100+30=2 ...

  8. LINQ学习——Group

    一.Group的作用 1.Group字句把select的对象根据一些标准进行分组. 2.从查询表达式返回的对象是从查询中枚举分组结果的可枚举类型. 3.每一个分组由一个叫做键的字段区分. 4.每一个分 ...

  9. PHP failed to ptrace(PEEKDATA) pid 13659: Input/output error错误解决方法

    PHP failed to ptrace(PEEKDATA) pid 13659: Input/output error错误解决方法 现在改linux内核文件打开限制<pre>ulimit ...

  10. oracle直接调用web services

    oracle调用C#开发web services 1,  去oracle官网上下载dbws-callout-utility-10131.zip 地址:https://oracle-base.com/a ...