无论是 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 -versionopenjdk version "1.8.0_201"OpenJDKRuntimeEnvironment(build 1.8.0_201-Huawei_JDK_V100R001C00SPC060B003-b10)OpenJDK64-BitServer VM (build 25.201-b10, mixed mode)

2. 下载软件

官网的下载地址页面:

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.gztar -xzvf hbase-2.1.5-bin.tar.gzmkdir -p /opt/localmv hbase-2.1.5/opt/local/hbase

配置HBase执行命令路径:

export HBASE_HOME=/opt/local/hbaseexport PATH=$PATH:$HBASE_HOME/bin

3. 配置软件

vim conf/hbase-env.sh

#JDK安装目录export JAVA_HOME=/usr/local/jre1.8.0_201#配置hbase自己管理zookeeperexport 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会自动创建相应的目录。

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

4. 启动软件

start-hbase.sh

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

2019-07-1107: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 serialization2019-07-11 07:37:23,664 INFO  [localhost:33539.activeMasterManager] master.AssignmentManager: Clean cluster startup. Assigning user regions2019-07-11 07:37:23,665 INFO  [localhost:33539.activeMasterManager] master.AssignmentManager: Joined the cluster in 11ms, failover=false2019-07-11 07:37:23,672 INFO  [localhost:33539.activeMasterManager] master.TableNamespaceManager: Namespace table not found. Creating...

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

ps -ef |grep hadooproot     1104911032207:37 pts/100: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 startroot     1890730747007:50 pts/100:00:00 grep --color=auto hadoop

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

# jps5701Jps4826HMaster1311 jar

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

host:/opt/local/hbase/data # ls -lh .total 36Kdrwx------. 4 root root 4.0KJul1108:08 datadrwx------. 4 root root 4.0KJul1108:08 hbase-rw-r--r--. 1 root root   42Jul1108:08 hbase.id-rw-r--r--. 1 root root    7Jul1108:08 hbase.versiondrwx------. 2 root root 4.0KJul1108:08MasterProcWALsdrwx------. 2 root root 4.0KJul1108:08 oldWALsdrwx------. 3 root root 4.0KJul1108:08.tmpdrwx------. 3 root root 4.0KJul1108:08WALsdrwx------. 3 root root 4.0KJul1108: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命令

Version2.1.5, r76ab087819fe82ccf6f531096e18ad1bed079651, WedJun516:48:11 PDT 2019
hbase(main):001:0> status1 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> listTABLEDeviceState1 row(s) in0.0090 seconds
=> ["DeviceState"]
hbase(main):003:0> describe "DeviceState"TableDeviceStateis ENABLEDDeviceStateCOLUMN FAMILIES DESCRIPTION{NAME => 'name', BLOOMFILTER => 'ROW', VERSIONS => '1', IN_MEMORY => 'false', KEEP_DELETED_CELLS => 'FALSE', DATA_BLOCK_ENCODING => 'NONE', TTL => 'FOREVER', COMPRESSION => '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', COMPRESSION => 'NONE', MIN_VERSIONS => '0', BLOCKCACHE => 'true', BLOCKSIZE => '65536', REPLICATION_SCOPE => '0'}2 row(s) in0.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\xAD1 row(s) in0.0230 seconds
hbase(main):013:0> get"DeviceState","row1", "name"COLUMN                                      CELL name:                                      timestamp=1562834473008, value=\xE7\x94\xB5\xE8\xA7\x86\xE6\x9C\xBA1 row(s) in0.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\xAD2 row(s) in0.0250 seconds

查询数量

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

删除某列、某行

delete"DeviceState", "row1", "name"0 row(s) in0.0080 seconds
hbase(main):003:0> deleteall "DeviceState", "row2"0 row(s) in0.1290 seconds

清空整个表数据

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

删除表(需要先disable)

hbase(main):006:0> disable "DeviceState"0 row(s) in2.2690 seconds
hbase(main):007:0> drop "DeviceState"0 row(s) in1.2880 seconds

五、FAQ

  • A. 启动时提示 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>
  • B. 启动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/tempexport HBASE_OPTS="-XX:+UseConcMarkSweepGC -Djava.io.tmpdir=$HBASE_TMP_DIR"

本文公众号来源:美码师
作者:美码师

连接:http://www.itpub.net/2019/12/02/4543/

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

  1. HBase入门篇

    目录: 1-HBase的安装 2-Java操作HBase例子 3-HBase简单的优化技巧 4–存储 5(集群) -压力分载与失效转发 6 -白话MySQL(RDBMS)与HBase之间 7 -安全& ...

  2. Hadoop基础-MapReduce入门篇之编写简单的Wordcount测试代码

    Hadoop基础-MapReduce入门篇之编写简单的Wordcount测试代码 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 本文主要是记录一写我在学习MapReduce时的一些 ...

  3. Hadoop生态圈-大数据生态体系快速入门篇

    Hadoop生态圈-大数据生态体系快速入门篇 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 一.大数据概念 1>.什么是大数据 大数据(big data):是指无法在一定时间 ...

  4. Hadoop生态圈-Hive快速入门篇之Hive环境搭建

    Hadoop生态圈-Hive快速入门篇之Hive环境搭建 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 一.数据仓库(理论性知识大多摘自百度百科) 1>.什么是数据仓库 数据 ...

  5. mongodb入门篇

    MongoDB 入门篇 分类: NoSQL, 故障解决 undefined 1.1 数据库管理系统 在了解MongoDB之前需要先了解先数据库管理系统 1.1.1 什么是数据? 数据(英语:data) ...

  6. Membership三步曲之入门篇 - Membership基础示例

    Membership 三步曲之入门篇 - Membership基础示例 Membership三步曲之入门篇 -  Membership基础示例 Membership三步曲之进阶篇 -  深入剖析Pro ...

  7. spring boot(一):入门篇

    构建微服务:Spring boot 入门篇 什么是spring boot Spring Boot是由Pivotal团队提供的全新框架,其设计目的是用来简化新Spring应用的初始搭建以及开发过程.该框 ...

  8. 1. web前端开发分享-css,js入门篇

    关注前端这么多年,没有大的成就,就入门期间积累了不少技巧与心得,跟大家分享一下,不一定都适合每个人,毕竟人与人的教育背景与成长环境心理活动都有差别,但就别人的心得再结合自己的特点,然后探索适合自己的学 ...

  9. 一个App完成入门篇(七)- 完成发现页面

    第七章是入门篇的倒数第二篇文章了,明天整个APP将进入收官. 本节教程主要要教会大家使用二维码扫描和用do_WebView组件加在html页面. 导入项目 do_WebView组件 扫描功能 自定义事 ...

随机推荐

  1. Python3 - 数字类型

    在 Python 中,数字并不是一个真正的对象类型,而是一组类似类型的分类.Python 不仅支持通常的数字类型(整数和浮点数),而且还能够通过常量去直接创建数字以及处理数字的表达式.数字数据类型是不 ...

  2. PV、UV、UIP、VV、DAU、CTR指的是什么?

    PV(page view) 网站浏览量,指网页的浏览次数,用户每打开一次页面就记录一次PV,多次打开则累加. UV(unique vistor) 独立访客数,指的是某一天访问某站点的人数,以cooki ...

  3. 魔法 [线段树优化DP]

    也许更好的阅读体验 \(\mathcal{Description}\) 小 \(D\) 正在研究魔法. 小 \(D\) 得到了远古时期的魔法咒语 \(S\),这个咒语共有 \(n\) 个音节,每个音节 ...

  4. eclipse创建springboot项目的三种方法

    本文链接:https://blog.csdn.net/mousede/article/details/81285693 方法一 安装STS插件 安装插件导向窗口完成后,在eclipse右下角将会出现安 ...

  5. highcharts离线导出图表

    到了这里,其实还没有结束,导出图片时,仍会发出两个请求 此时找到offline-exporting.js文件修改其中的libURL 修改为请求自己的网站

  6. DotNet Core 2.2 MVC Razor 页面编译为 View.dll 文件的解决方法

    使用文本文件编辑器打开项目文件,找到: <PropertyGroup>     <TargetFramework>netcoreapp2.0</TargetFramewo ...

  7. 利用nfs-client-provisioner动态提供Kubernetes后端存储卷

    原文:https://www.kubernetes.org.cn/3894.html 利用NFS client provisioner动态提供Kubernetes后端存储卷 本文翻译自nfs-clie ...

  8. 2019三六零 java面试笔试题 (含面试题解析)

    本人3年开发经验.18年年底开始跑路找工作,在互联网寒冬下成功拿到阿里巴巴.今日头条.360等公司offer,岗位是Java后端开发,最终选择去了三六零. 面试了很多家公司,感觉大部分公司考察的点都差 ...

  9. pandas-07 DataFrame修改index、columns名的方法

    pandas-07 DataFrame修改index.columns名的方法 一般常用的有两个方法: 1.使用DataFrame.index = [newName],DataFrame.columns ...

  10. 【面试突击】-缓存击穿(布隆过滤器 Bloom Filter)

    原文地址:https://blog.csdn.net/fouy_yun/article/details/81075432 前面的文章介绍了缓存的分类和使用的场景.通常情况下,缓存是加速系统响应的一种途 ...