HBase学习总结

HBase的下载与安装
 
(HBase是一种数据库:Hadoop数据库,它是一种NoSQL存储系统,专门设计用来快速随机读写大规模数据。本文介绍HBase的下载与安装的整个过程。) 
一、HBase的下载 
1.登录HBase官网 http://hbase.apache.org/ ,可看到如图1所示的页面: 

图1 登录HBase官网的页面

2.点击图1中的红色小框中的“here”,进入如图2所示的页面。 

图2 下载链接

3.点击图2中的红色小框中的链接,进入如图3所示的下载页面。 


图3 下载页面

点击文件名便可以下载所需要的HBase安装包和源代码,本文示例中使用的是HBase 1.0.1版本。

二、HBase的安装 
将下载的安装包(hbase-1.0.1-bin.tar.gz)上传到Linux机器上。为了避免文件权限的问题,建议将该安装包上传到root用户下。在本文中,安装包存放在“/root/zhouzx”目录下。由于本次安装HBase的目的是自己学习,因此只是安装了单机版。HBase真正的威力体现在集群中,这是大数据项目中采用的部署方式。 
1.解压安装包 
执行“tar -zxvf hbase-1.0.1-bin.tar.gz”命令解压安装包,得到“hbase-1.0.1”。转到该目录下,可以看到有如下文件及目录:
-rw-r--r--  1 root root 140371 Apr 18 13:02 CHANGES.txt
-rw-r--r--  1 root root  11358 Jan 25 17:47 LICENSE.txt
-rw-r--r--  1 root root    897 Apr 18 12:55 NOTICE.txt
-rw-r--r--  1 root root   1477 Apr  6 06:03 README.txt
drwxr-xr-x  4 root root   4096 Apr 18 12:58 bin
drwxr-xr-x  2 root root   4096 Apr 18 12:55 conf
drwxr-xr-x 12 root root   4096 Apr 18 13:14 docs
drwxr-xr-x  7 root root   4096 Apr 18 13:08 hbase-webapps
drwxr-xr-x  3 root root   4096 Jun 26 09:07 lib

到这里,HBase的安装已经可以告一段落了,下面来设置环境。

2.部署jdk并设置java环境 
要想让HBase成功运行,还需要在Linux机器上部署jdk,并设置java环境。为了支持最新的HBase版本,建议部署的jdk的版本在1.7.0以上。 
将“jdk1.7.0-linux.tar.gz”上传到“/usr/java”目录下,运行“tar -zxvf jdk1.7.0-linux.tar.gz”命令,得到“/usr/java/jdk1.7.0”目录下的内容。 
接下来需要在root用户(安装HBase的用户)下设置java环境。在root用户下执行“vi .bash_profile”命名,并将以下命令拷贝到该文件中:
export JAVA_HOME=/usr/java/jdk1.7.0
export PATH=$JAVA_HOME/bin:$PATH
export CLASSPATH=.:$JAVA_HOME/lib/dt.jar:$JAVA_HOME/lib/tools.jar


然后执行“:wq”命令保存文件内容。此时,环境变量已设置完成。为了确定环境变量是否已设置成功,可直接执行“java -version”命令,如果出现以下内容:
java version "1.7.0_60"
Java(TM) SE Runtime Environment (build 1.7.0_60-b19)
Java HotSpot(TM) 64-Bit Server VM (build 24.60-b09, mixed mode)

则表示部署jdk和设置java环境已成功。

3.启动和停止HBase 
转到“/root/zhouzx/hbase-1.0.1/bin”目录下,执行“sh start-hbase.sh”或“./start-hbase.sh”命令启动HBase。如果出现以下内容:
starting master, logging to /root/zhouzx/hbase-1.0.1/bin/../logs/hbase-root-master-A10168992.out

则表示HBase启动成功。 
接着,执行“sh stop-hbase.sh”或“./stop-hbase.sh”命令停止HBase。如果出现以下内容:
stopping hbase.................


则表示HBase已停止运行。
 
 
HBase介绍及其基本操作
(HBase是一种数据库:Hadoop数据库,它是一种NoSQL存储系统,专门设计用来快速随机读写大规模数据。在已成功安装并正常启动的前提下,本文介绍HBase的基本操作。) 
一、HBase简介 
什么是HBase(Hadoop Database)呢?有以下两种常见的说法: 
第一,它是一种稀疏的、分布式的、持久化的、多维有序映射,它基于行键(row key)、列键(column key)和时间戳(timestamp)建立索引。 
第二,它是一种键值(key value)存储,面向列族的数据库,有时也是一种存储多时间戳版本映射的数据库。 
以上两种描述都是对的。但从根本上来说,HBase是一个高可靠性、高性能、面向列、可伸缩的分布式存储系统,是一个可以随机访问的存储和检索数据的平台。大家可以按照需要写入数据,然后再按照需要读取数据。

HBase有如下特点: 
第一,它不介意数据类型,允许动态的、灵活的数据模型,并不限制存储的数据的种类。因此,它可以自如地存储结构化和半结构化的数据。 
第二,它不用SQL语言,也不强调数据之间的关系。 
第三,它不允许跨行的事务,可以在一行的某一列存储一个整数,而在另一行的同一列存储字符串。 
第四,它被设计成在一个服务器集群上运行,而不是单台服务器。这意味着一种强大的、可扩展的数据的使用方式。 
从HBase的特点可以看出,HBase的设计与目标都与传统的关系型数据库不同。

二、HBase的基本操作 
在已成功安装并正常启动HBase的前提下,我们可以使用HBase Shell,通过命令行方式与HBase进行交互。 
1.启动HBase Shell 
转到HBase解压包的“bin”目录下,使用命令“./hbase shell”或“sh hbase shell”命令即可启动HBase Shell。启动之后的信息如下:
HBase Shell; enter 'help<RETURN>' for list of supported commands.
Type "exit<RETURN>" to leave the HBase Shell
Version 1.0.1, r66a93c09df3b12ff7b86c39bc8475c60e15af82d, Fri Apr 17 22:14:06 PDT 2015

hbase(main):001:0>


为了验证HBase是否安装成功,我们可以输入“list”查看HBase中所有的表。该命令的执行情况如下:
hbase(main):001:0> list
TABLE                                                                                                                            
0 row(s) in 0.2390 seconds

=> 


由于是首次登录,因此HBase中包含了0个表。

2.创建表 
HBase使用表作为顶级结构来存储数据,写数据到HBase,也就是写数据到表。下面创建一个有一个列族(“cf”)的表“mytable”:
hbase(main):002:0> create 'mytable', 'cf'
0 row(s) in 0.3250 seconds

=> Hbase::Table - mytable
hbase(main):003:0> list
TABLE                                                                                                                            
mytable                                                                                                                          
1 row(s) in 0.0090 seconds

=> ["mytable"]


使用“list”命令,我们可以看到,表创建成功。

3.写数据 
表创建好之后,就需要写入一些数据。例如,我们想往表里写入“hello hbase”,那么我们就在“mytable”表的“first”行中的“cf:info”列对应的数据单元中插入“hello hbase”。命令执行如下:
hbase(main):004:0> put 'mytable', 'first', 'cf:info', 'hello hbase'
0 row(s) in 0.0970 seconds


我们还可以继续多增加几个值,如下:
hbase(main):005:0> put 'mytable', 'second', 'cf:name', 'zhou'
0 row(s) in 0.0180 seconds

hbase(main):006:0> put 'mytable', 'third', 'cf:nation', 'China'
0 row(s) in 0.0080 seconds


现在表里面有3行和3个数据单元。在使用列的时候,大家并没有提前定义这些列,也没有定义往每个列中存储的数据类型。因此,HBase是一种无模式的数据库。

4.读数据 
HBase有两种方式读取数据:get和scan。get方式可以读取一行的数据信息,scan方式可以读取表中所有行的数据信息。 
get命令执行如下:
hbase(main):008:0> get 'mytable', 'first'
COLUMN                            CELL                                                                                           
 cf:info                          timestamp=1435548279711, value=hello hbase                                                     
1 row(s) in 0.0770 seconds


该命令输出了该行所有的数据单元。

scan命令执行如下:
hbase(main):009:0> scan 'mytable'
ROW                 COLUMN+CELL                                                                                    
 first                  column=cf:info, timestamp=1435548279711, value=hello hbase                                     
 second                column=cf:name, timestamp=1435548751549, value=zhou                                            
 third                  column=cf:nation, timestamp=1435548760826, value=China                                         
3 row(s) in 0.0320 seconds


该命令返回了所有数据。HBase返回行的顺序,是按照行的名字排序的。HBase称之为行键(rowkey)。

5.删除表 
要想删除一张表,需要先将其“disable”掉,然后再“drop”掉。命令执行如下:
hbase(main):010:0> disable 'mytable'
0 row(s) in 1.2380 seconds

hbase(main):011:0> drop 'mytable'
0 row(s) in 0.1770 seconds

hbase(main):012:0> list
TABLE                                                                                                                            
0 row(s) in 0.0070 seconds

=> 


HBase还有很多技巧,但是其他所有的东西都是建立在上面那些基本操作基础之上的。大家一定要好好体会。
 
 
HBase的数据模型及工作机制
一、HBase数据模型 
HBase模式里的逻辑实体包括: 
(1)表(table):HBase用表来组织数据。表名是字符串(String),由可以在文件系统路径里使用的字符组成。 
(2)行(row):在表里,数据按行存储。行由行键(rowkey)唯一标识。行键没有数据类型,总是视为字节数组byte 。 
(3)列族(column family):行里的数据按照列族分组,列族也影响到HBase数据的物理存放,因此,它们必须事前定义并且不轻易修改。表中每行拥有相同列族,尽管行不需要在每个列族里存储数据。列族名字是字符串(String),由可以在文件系统路径里使用的字符组成。 
(4)列限定符(column qualifier):列族里的数据通过列限定符或列来定位。列限定符不必事前定义,列限定符不必在不同行之间保持一致。就像行键一样,列限定符没有数据类型,总是视为字节数组byte 。 
(5)单元(cell):行键、列族和列限定符一起确定一个单元。存储在单元里的数据称为单元值(value)。值也没有数据类型,总是视为字节数组byte 。 
(6)时间版本(version):单元值有时间版本。时间版本用时间戳标识,是一个long。没有指定时间版本时,当前时间戳作为操作的基础。HBase保留单元值时间版本的数量基于列族进行配置,默认数量是3个。 
HBase的每个数据值使用坐标来访问。一个值的完整坐标包括行键、列族、列限定符和时间版本。由于把所有坐标视为一个整体,因此HBase可以看作是一个键值(key-value)数据库。

例如,在《HBase学习总结(2):HBase介绍及其基本操作》( http://blog.csdn.net/zhouzhaox ... 68229 1)中: 
(1)表名是“mytable”。 
(2)行是“first”、“second”和“third”。 
(3)列族是“cf”。 
(4)列限定符是“info”、“name”和“nation”。 
(5)单元值是“hello hbase”、“zhou”和“China”。 
(6)时间戳是“1435548279711”、“1435548751549”和“1435548760826”。

二、HBase工作机制 
1.HBase写路径 
在HBase中无论是增加新行还是修改已有的行,其内部流程都是相同的。默认情况下,执行写入时会写到两个地方:预写式日志(write-ahead log,WAL,也称HLog)和MemStore。HBase的默认方式是将写入动作记录在这两个地方,以保证数据持久化。只有当这两个地方的变化信息都写入并确认之后,才认为写动作完成。写入过程如图1所示。 
 
图1 HBase同时向WAL和MemStore执行写入 
 
MemStore是内存里的写入缓冲区,HBase中数据在永久写入磁盘之前在这里积累。当MemStore填满之后,其中的数据会刷写到硬盘,生成一个HFile。HFile是HBase使用的底层存储格式。HFile对应于列族,一个列族可以有多个HFile,但一个HFile不能存储多个列族的数据。在集群的每个节点上,每个列族有一个MemStore。MemStore生成HFile的过程如图2所示。 

图2 MemStore生成HFile 

如果MemStore还没有刷写,服务器就崩溃了,内存中没有写入硬盘的数据就会丢失。HBase的应对办法是在写动作完成之前先写入WAL。HBase集群中每台服务器维护一个WAL来记录发生的变化。WAL是底层文件系统上的一个文件。直到WAL新记录成功写入后,写动作才会被认为成功完成。这可以保证HBase和支撑它的文件系统满足持久性。大多数情况下,HBase使用Hadoop分布式文件系统(HDFS)来作为底层文件系统。 
如果HBase服务器宕机,没有从MemStore里刷写到HFile的数据将可以通过回放WAL来恢复。你不需要手工执行。HBase的内部机制中有恢复流程部分来处理。每台HBase服务器有一个WAL,这台服务器上的所有表(和它们的列族)共享这个WAL。 
值得注意的是,不写入WAL会在RegionServer故障时增加丢失数据的风险。关闭WAL,出现故障时HBase可能无法恢复数据,没有刷写到硬盘的所有写入数据都会丢失。

2.HBase读路径 
如果想快速访问数据,通用的原则是数据保持有序并尽可能保存在内存里。HBase实现了这两个目标,大多数情况下读操作可以做到毫秒级。HBase读动作必须重新衔接持久化到硬盘上的HFile和内存中MemStore里的数据。HBase在读操作上使用了LRU(最近最少使用算法)缓存技术。这种缓存也叫做BlockCache,和MemStore在一个JVM堆里。BlockCache设计用来保存从HFile里读入内存的频繁访问的数据,避免硬盘读。每个列族都有自己的BlockCache。 
掌握BlockCache是优化HBase性能的一个重要组成部分。BlockCache中的Block是HBase从硬盘完成一次读取的数据单位。HFile物理存放形式是一个Block的序列外加这些Block的索引。这意味着,从HBase里读取一个Block需要先在索引上查找一次该Block,然后从硬盘读出。Block是建立索引的最小数据单位,也是从硬盘读取的最小数据单位。Block大小按照列族设定,默认值是64KB。根据使用场景你可能会调大或者调小该值。Block变小会导致索引变大,进而消耗更多内存;Block变大意味着索引项变少,索引变小,因此节省内存。 
从HBase中读出一行,首先会检查MemStore等待修改的队列,然后检查BlockCache看包含该行的Block是否最近被访问过,最后访问硬盘上的对应HFile。整个读入过程如图3所示。 

图3 HBase读入过程

注意,HBase存放某个时刻MemStore刷写时的快照,一个完整行的数据可能存放在多个HFile中。为了读出完整行,HBase可能需要读取包含该行信息的所有HFile。

3.HBase的合并 
删除命令并不是立即删除内容,它只是给记录打上了删除的标记。就是说,针对那个内容的一条“墓碑”(tombstone)记录写入进来,作为删除的标记。墓碑记录用来标志删除的内容不能在get和scan命令中返回结果。因为HFile文件是不能改变的,直到执行一次大合并,这些墓碑记录才会被处理,被删除记录占用的空间才会被释放。 
合并分为两种:大合并(major compaction)和小合并(minor compaction)。两种将会重整存储在HFile里的数据。小合并把多个小HFile合并生成一个大HFile。因为读出一条完整的行可能引用很多文件,限制HFile的数量对于读性能很重要。执行合并时,HBase读出已有的多个HFile的内容,把记录写入一个新文件。然后,把新文件设置为激活状态,删除构成这个新文件的所有老文件。HBase根据文件的号码和大小决定合并哪些文件。小合并设计出发点是轻微影响HBase的性能,所以涉及的HFile的数量有上限。这些都可以设置。小合并的示意如图4所示。 

图4 小合并的示意图

大合并将处理给定region的一个列族的所有HFile。大合并完成后,这个列族的所有HFile合并成一个文件。可以从Shell中手工触发整个表(或者特定region)的大合并。这个动作相当耗费资源,不要经常使用。另一方面,小合并是轻量级的,可以频繁发生。大合并是HBase清理被删除记录的唯一机会。因为我们不能保证被删除的记录和墓碑标记记录在一个HFile里面,而大合并可以确保同时访问到两种记录。
 
 
HBase的工作原理
一、切分和分配大表 
HBase中的表是由行和列组成的。HBase中的表可能达到数十亿行和数百万列。每个表的大小可能达到TB级,有时甚至PB级。这些表会切分成小一点儿的数据单位,然后分配到多台服务器上。这些小一点儿的数据单位叫region。托管region的服务器叫RegionServer。一张表由多个小一点的region组成,如图1所示。 
 
图1 多个小一点的region组成一张表 

RegionServer和HDFS DataNode典型情况下并列配置在同一物理硬件上,如图2所示。RegionServer本质上是HDFS客户端,在上面存储/访问数据。主(master)进程分配region给RegionServer,每个RegionServer一般托管多个region。 

图2 RegionServer和DataNode典型情况下并列配置在同一台主机上 

考虑到基础数据存储在HDFS上,所有客户端都可以在一个命名空间下访问。所有RegionServer都可以访问文件系统里同一个文件,因此RegionServer可以托管任何region,如图3所示。通过DataNode和RegionServer并列配置,理论上RegionServer可以把本地DataNode作为主要DataNode进行读写操作。 
 
图3 RegionServer托管region的示意图 

单个region大小由hbase-site.xml文件里的配置参数HBase.hregion.max.filesize决定,当一个region大小变得大于该值时,它会切分成两个region。

二、如何找到region 
当一个region分配给RegionServer时,客户端应用如何知道它的位置? 
HBase中有两个特殊的表,-ROOT-和.META.,用来查找各种表的region位置在哪里。-ROOT-和.META.也会切分成region,其中,-ROOT-永远不会切分超过一个region,.META.和其他表一样可以按需切分成许多region。 
当客户端应用要访问某行时,它先找-ROOT-表,查找什么地方可以找到负责某行的region。-ROOT-指向.META.表的region去寻找答案。.META.表由入口地址组成,客户端应用使用这个入口地址判断哪一个RegionServer托管待查找的region。这个查找过程就像是一个3层分布式B+树(如图4所示),-ROOT-表是B+树的-ROOT-节点,.META. region是-ROOT-节点的叶子,用户表的region是.META. region的叶子。 

图4 -ROOT-、.META.和用户表的B+树视图 

在图4中,-ROOT-表只包含了一个region,托管在RegionServer RS1上;.META.表包含了3个region,托管在RS1、RS2和RS3上面;用户表T1和T2分别包含3个和4个region,分别在RS1、RS2和RS3上面。 

图5 HBase中的表分布在各个RegionServer上

如图5所示,RegionServer 1(RS1)托管用户表T1的region R1和.META.表的region M2;RegionServer 2(RS2)托管用户表的region R2、R3和.META.表的region M1;RegionServer 3(RS3)只托管了-ROOT-。

三、如何找到-ROOT-表 
一个叫做ZooKeeper的系统提供了HBase系统的入口点。ZooKeeper是一种集中服务,用来维护配置信息、命名服务、提供分布式同步和提供分组服务等。这是一种高可用的、可靠的分布式配置服务。 
客户端与HBase系统的交互分几个步骤,ZooKeeper是入口点。整个交互过程如图6所示。 

图6 客户端与HBase系统的交互过程

从图6可以看出,交互步骤为: 
第一步:客户端询问ZooKeeper,-ROOT-在哪里? 
第二步:ZooKeeper回复客户端,-ROOT-在RegionServer RS1上面。 
第三步:客户端询问在RS1上的-ROOT-表,哪一个.META. region可以找到表T1里的行00007? 
第四步:RS1上的-ROOT-表回复客户端,在RegionServer RS3上的.META. region M2可以找到。 
第五步:客户端询问RS3上的.META. region M2,在哪一个region上可以找到表T1里的行00007以及哪一个RegionServer为它提供服务? 
第六步:RS3上的.META. region M2回复客户端,数据在RegionServer RS3上面的region T1R3上。 
第七步:客户端发消息给RS3上面的region T1R3,要求读取行00007。 
第八步:RS3上面的region T1R3将数据返回给客户端。
 
 
 
HBase表设计
一、如何开始模式设计 
当我们说到模式(schema),要考虑以下内容: 
(1)这个表应该有多少个列族? 
(2)列族使用什么数据? 
(3)每个列族应该有多少列? 
(4)列名应该是什么?(尽管列名不必在建表时定义,但是读写数据时是需要知道的。) 
(5)单元存放什么数据? 
(6)每个单元存储多少个时间版本? 
(7)行键结构是什么?应该包括什么信息? 
1.问题建模 
一个特定列族的所有数据在HDFS上会有一个物理存储。这个物理存储可能由多个HFile组成,理想情况下可以通过合并得到一个HFile。一个列族的所有列在硬盘上存放在一起,使用这个特性可以把不同访问模式的列放在不同列族,以便隔离它们。这也是HBase被称为面向列族的存储(column-family-oriented store)的原因。 
在模式设计流程中尽早定义访问模式,以便通过它们检验你的设计决定。 
为了定义访问模式,第一步最好定义想使用表来回答什么问题。

2.需求定义:提前多做准备工作总是有好处的 
列限定符可以按数据处理,就像值。这和关系型系统不同,关系型系统的列名是固定的并且需要在建表时预先定义。 
HBase没有跨行事务的概念,要避开在客户端代码里需要事务逻辑的设计,因为这会让你不得不维护复杂的客户端。

3.均衡分布数据和负载的建模方法 
HBase的运算速度涉及很多考量因素。具体包括: 
(1)表中KeyValue条目数量(包括put的结果和delete留下的墓碑标记)。 
(2)HFile里数据块(HFile block)的数量。 
(3)平均一个HFile里KeyValue条目的数量。 
(4)每行里列的平均数量。 
e代表任何指定时间在MemStore里的条目数量,因为MemStore是使用跳表(skip list)实现的,所以查找行的时间复杂度是O(log e)。 
宽表(wide table)的一行包括很多列。高表(tall table)是一种新模式,HFile里的KeyValue对象存储列族名字,使用短的列族名字在减少硬盘和网络I/O方面很有帮助。 
HBase语境中的热点指的是负载极度集中在一小部分region上。因为负载没有分散在整个集群上,这是不合理的。服务这些region的几台机器承担了绝大部分工作,将成为整体性能的瓶颈。

4.目标数据访问 
HBase表里只有键(KeyValue对象的Key部分,包括行键、列限定符和时间戳)可以建立索引。访问一个特定行的唯一办法是通过行键。 
在列限定符和时间戳上建立索引,可以让你在一行上不用扫描前面所有的列而直接跳到正确的列。 
从表中获取数据有两种方式,即get和scan。如果需要一行,可以使用get调用,这种情况下必须提供行键;如果想执行一次扫描(scan),如果知道起始和停止键,可以选择使用它们来限制扫描器对象扫描的行数。 
根据指定的键的某个部分,可以限制读取硬盘的数据量或者网络传输的数据量。指定行键则只返回需要的行,但是服务器返回整行给客户端。指定列族让你进一步限制读取行的什么部分,因为如果行键跨多个列族,可以只读取HFile的一个子集。进一步指定列限定符和时间戳,可以让你减少返回客户端的列数,因此节省了网络I/O。 
把数据放入单元值和把它放入列限定符或行键将占用相同的存储空间,但是把数据从单元移到行键将可能得到更好的性能。 
一些基础知识: 
(1) HBase表很灵活,可以用字符数组形式存储任何东西。 
(2) 在同一列族里存储相似访问模式的所有数据。 
(3) 索引建立在KeyValue对象的Key部分上,Key由行键、列限定符和时间戳按次序组成。 
(4) 高表可能支持你把运算复杂度降到O(1),但是要在原子性上付出代价。 
(5) 设计HBase模式时进行反规范化处理是一种可行的办法。 
(6) 想想如何能够在单个API调用里而不是多个API调用里完成访问模式。HBase不支持跨行事务,要避免在客户端代码里维护这种复杂的逻辑。 
(7) 散列支持定长键和更好的数据分布,但是失去了排序的好处。 
(8) 列限定符可以用来存储数据,就像单元一样。 
(9) 因为可以把数据放入列限定符,所以它的长度影响存储空间。当访问数据时,它也影响了硬盘和网络I/O的开销,所以尽量简练。 
(10) 列族名字的长度影响了通过网络传回客户端的数据大小(在KeyValue对象里),所以尽量简练。

二、反规范化 
规范化是关系型数据库世界的一种技术,其中每种重复信息都会放进一个自己的表。这有两个好处:当发生更新或删除时,不用担心更新指定数据所有副本的复杂性;通过保存单一副本而不是多个副本,减少了占用的存储空间。需要查询时,在SQL语句里使用JOIN子句重新联结这个数据。 
反规范化是一个相反概念。数据是重复的,存在多个地方。因为你不再需要开销很大的JOIN子句,这使得查询数据变得更容易、更快。 
从性能观点看,规范化为写做优化,而反规范化为读做优化。 


三、相同表里的混杂数据 
尽可能分离不同的访问模式。

四、行键设计原则  
在设计HBase表时,行键是唯一重要的事情,应该基于预期的访问模式来为行键建模。 
行键决定了访问HBase表时可以得到的性能。这个结论根植于两个事实:region基于行键为一个区间的行提供服务,并且负责区间内每一行;HFile在硬盘上存储有序的行。当region刷写留在内存里的行时生成了HFile。这些行已经排过序,也会有序地刷写到硬盘上。HBase表的有序特性和底层存储格式可以让你根据如何设计行键以及把什么放入列限定符来推理其性能表现。 
关系型数据库可以在多个列上建立索引,但HBase只能在键上建立索引,访问数据的唯一办法是使用行键。如果不知道想访问的数据的行键,就必须扫描相当多的行。

五、I/O考虑 
以下技巧针对访问模式对设计行键进行优化。 
1.为写优化 
应该如何把数据分散在多个region上呢? 
(1)散列 
如果你愿意在行键里放弃时间戳信息,使用原始数据的散列值作为行键是一种可能的解决方案。 
散列算法有一个非零碰撞概率。使用散列函数的方式也很重要。 
(2)salting 
在思考行键的构成时,salting是一种技巧。

2.为读优化 
尽量把较少的HFile数据块读入内存,来获得要寻找的数据集。因为数据存储在一起,每次读取HFile数据块时可以比数据分散存储时得到更多的信息。 
这里行键的结构对于读性能很重要。

3.基数和行键结构 
有效的行键设计不仅要考虑把什么放入行键中,而且要考虑它们在行键里的位置。 
信息在行键里的位置和选择放入什么信息同等重要。

六、从关系型到非关系型 
从关系型数据库知识映射到HBase没有捷径,它们是不同的思考方式。 
关系型数据库和HBase是不同的系统,它们拥有不同的设计特性,可以影响到应用系统的设计。 
1.一些基本概念 
关系型数据库建模包括3个主要概念: 
a.实体(entity)—映射到表(table)。 
b.属性(attribute)—映射到列(column)。 
c.联系(relationship)—映射到外键(foreign-key)。 
(1)实体 
在关系型数据库和HBase中,实体的容器(container)是表,表中每行代表实体的一个实例。用户表中每行代表一个用户。 
(2)属性 
为了把属性映射到HBase,必须区分至少两种属性类型: 
a.识别属性(identifying attribute):这种属性可以唯一地精确识别出实体的一个实例(也就是一行)。关系型表里,这种属性构成表的主键(primary key)。在HBase中,这种属性成为行键(rowkey)的一部分。 
一个实体经常是由多个属性识别出来的,这一点正好映射到关系型数据库里的复合键(compound keys)概念。 
b.非识别属性(non-identifying attribute):在HBase中,它们基本映射到列限定符。 
(3)联系 
逻辑关系模型使用两种主要联系:一对多和多对多。在关系型数据库中,把前者直接建模为外键(foreign key),把后者建模为连接表(junction table)。 
HBase没有内建的联结(join)或约束(constrain),几乎不使用显示联系。

2.嵌套实体 
HBase的列(也叫做列限定符)不需要在设计时预先定义。它们可以是任何东西。HBase具有在一个父实体或主实体的行里嵌套另一个实体的能力,但这远远不是一个灵活的模式行(flexible schema row)。 
  
嵌套的实体是从关系型映射到非关系型的又一个工具。 
如果你得到子实体的唯一方法是通过父实体,并且你希望在一个父实体的所有子实体上有事务级保护,这种技术是最正确的选择。

七、列族高级配置 
1.可配置的数据块大小 
HFile数据块大小可以在列族层次设置。数据块索引存储每个HFile数据块的起始键。数据块大小配置会影响数据块索引的大小。数据块越小,索引越大,因而占用的内存空间越大。同时,因为加载进内存的数据块更小,随机查找性能更好。

2.数据块缓存 
把数据放进读缓存,但工作负载却经常不能从中获得性能提升。

3.激进缓存 
可以选择一些列族,赋予它们在数据块缓存里有更高的优先级(LRU缓存)。

4.布隆过滤器 
布隆过滤器允许对存储在每个数据块的数据做一个反向测试。当某行被请求时,先检查布隆过滤器,看看该行是否不在这个数据块中。

5.生存时间(TTL)  
HBase可以让你在数秒内在列族级设置一个TTL,早于指定TTL值的数据在下一次大合并时会被删除。如果你在同一单元上有多个时间版本,早于设定TTL的版本会被删除。

6.压缩 
HFile可以被压缩并存放在HDFS上,HBase可以使用多种压缩编码,包括LZO、Snappy和GZIP。 
注意,数据只在硬盘上是压缩的,在内存里或通过网络传输时是没有压缩的。

7.单元时间版本 
在默认情况下,HBase每个单元维护3个时间版本,这个属性是可以设置的。 
同时也可以指定列族存储的最少时间版本数。

八、过滤数据 
过滤器也被称为下推判断器,支持你把数据过滤标准从客户端下推到服务器。 
较为常用的过滤器包括: 
1.行过滤器 
这是一种预装的比较过滤器,支持基于行键过滤数据。

2.前缀过滤器 
这是行过滤器的一种特例,它基于行键的前缀值进行过滤。

3.限定符过滤器 
它是一种类似于行过滤器的比较过滤器,不同之处是它用来匹配列限定符而不是行键。它使用与行过滤器相同的比较运算符和比较器类型。

4.值过滤器 
它提供了与行过滤器或限定符过滤器一样的功能,只是针对的是单元值。

5.时间戳过滤器 
它允许针对返回给客户端的时间版本进行更细粒度的控制。

6.过滤器列表 
组合使用多个过滤器经常是很有用的。

九、小结 
模式设计的出发点是问题,而不是关系。 
模式设计永远不会结束。 
数据规模是第一本质性的因素。 
每个维度都是一个提升性能的机会。
 
 
其它的HBase客户端选择
一、在UNIX里使用HBase Shell脚本
在关系型数据库中,模式迁移的管理是个头疼的问题,主要表现在两个方面:第一个是模式和应用的紧耦合关系,第二个是对数据库模式的变化的管理。
1.准备HBase Shell
启动命令:bin目录下执行./hbase shell或sh hbase shell。
2.使用UNIX Shell脚本创建表模式

二、通过REST访问HBase
REST服务作为一个独立的进程运行,它可以运行在任何能够与HBase通信的机器上。一个REST接口部署的网络拓扑如下图所示。

1.JPG


REST服务还支持很多种响应格式,所有端点支持XML、JSON和Protobufs。
1.启动HBase REST服务
启动命名:./hbase rest start -p 9999
2.访问特定的表

三、通过Python使用HBase Thrift网关
如果不用Java,那么最常见的访问HBase的方法是通过Thrift。Thrift是一种语言和一套生成代码的工具。

四、asynchbase:另外一种HBase Java客户端
asynchbase是另一种HBase客户端,也是用Java编写的。它是完全异步的,这意味着它不会阻塞调用应用的线程。

五、小结
为了管理模式迁移,建议使用HBase Shell进行脚本编程。
除了JVM之外,还可以选择REST和Thrift。
  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值