HBase简单介绍

(中文)HBase官方文档-0.97
(英文)Apache HBase Reference Guide

概述

NoSQL

HBase是一种”NoSQL”数据库。”NoSQL”是一个通用词表示数据库不是RDBMS(Relation Database Management System,关系型数据库管理系统),后者支持SQL作为主要访问手段。有许多种NoSQL数据库:BerkeleyDB是本地NoSQL数据库例子,而HBase是大型分布式数据库。技术上来说,HBase更像是”数据存储(Data Store)”多于”数据库(Data Base)”。因为缺少很多RDBMS特性,如列类型,第二索引,触发器,高级查询语言等。
然而,HBase有许多特征同时支持线性化和模块化扩充。HBase集群通过增加RegionServers进行扩充。它可以放在普通的服务器中。例如,如果集群从10个扩充到20个RegionServer,存储空间和处理容量都同时翻倍。RDBMS也能很好扩充,但仅对一个点,特别是对一个单独数据库服务器的大小,同时,为了更好的性能,需要特殊的硬件和存储设备。HBase特性:

  • 强一致性读写:HBase不是”最终一致性(eventually consistent)”数据存储。这让它很适合高速计数聚合类任务。
  • 自动分片(Automatic sharding):HBase表通过region分布在集群中。数据增长时,region会自动分割并重新分布。
  • RegionServer自动故障转移
  • Hadoop/HDFS集成:HBase支持本机外HDFS作为它的分布式文件系统。
  • MapReduce:HBase通过MapReduce支持大并发处理,HBase可以同时做源和目标。
  • Java客户端API:HBase支持易于使用的Java API进行编程访问。
  • Thrift/REST API:HBase也支持Thrift和REST作为非Java前端。
  • Block Cache和Bloom Filters:对于大容量查询优化,HBase支持Block Cache和Bloom Filters。
  • 运维管理:HBase提供内置网页用于运维视角和JMX度量。

什么时候用HBase

HBase不适合所有问题。
首先,确信有足够多数据,如果有上亿或上千亿行数据,HBase是很好的备选。如果只有上千或上百万行,则用传统的RDBMS可能是更好的选择。因为所有数据可以在一两个节点保存,集群其他节点可能闲置。
其次,确信可以不依赖所有RDBMS的额外特性(e.g.,列数据类型,第二索引,事务,高级查询语言等。)一个建立在RDBMS上应用,如不能仅通过改变一个JDBC驱动移植到HBase。相对于移植,需考虑从RDBMS到HBase是一次完全的重新设计。
第三,确信你有足够硬件。甚至HDFS在小于5个数据节点时,干不好什么事情(根据如HDFS块复制具有缺省值3),还要加上一个NameNode。
HBase能在单独的笔记本上运行良好。但这应仅当成开发配置。

HBase和Hadoop/HDFS的区别

HDFS是分布式文件系统,适合保存大文件。官方宣称它并非普通用途文件系统,不提供文件的个别记录的快速查询。另一方面,HBase基于HDFS且提供大表的记录快速查找(和更新)。这有时可能引起概念混乱。HBase内部将数据放到索引好的”存储文件(StoreFiles)”,以便高速查询。存储文件位于HDFS中。

Schema的设计

在HBase中,值是作为一个单元(Cell)保存在系统中的,要定位一个单元,需要行,列名和时间戳。无论是列族,属性和行键都会在数据中重复上亿次。

  • 行键
    • 让行键尽量短,但是需要保证他们依然对获取数据有用(e.g. Get vs. Scan)。对访问数据无用的短键,并不比带有get/scan属性的长键更好。行键的设计需要权衡。
    • 行键在列族范围内。所以同样的行键可以在同一个表的每个列族中存在而不会冲突。
    • 行键不能改变。唯一可以“改变”的方式是删除然后再插入。这是一个网上常问问题,所以要注意开始就要让行键正确(且/或在插入很多数据之前)。
  • 列族
    在HBase中列族是一些列的集合。一个列族所有列成员是有着相同的前缀。比如,列courses:history和courses:math都是列族courses的成员,冒号(:)是列族的分隔符,用来区分前缀和列名。column前缀必须是可打印的字符,剩下的部分(称为qualify),可以由任意字节数组组成。列族必须在表建立的时候声明。column就不需要了,随时可以新建。
    在物理上,一个的列族成员在文件系统上都是存储在一起。因为存储优化都是针对列族级别的,这就意味着,一个column family的所有成员的是用相同的方式访问的。
    • 尽量使列族名小,最好一个字符。(如”d”表示data/default)。
    • 尽管详细属性名(如,”myVeryImportantAttribute”)易读,在HBase中最好使用短属性名(e.g., “via”)保存。
    • 列族可以设置TTL(Time To Live,存活时间)秒数,HBase在超时后将自动删除数据。影响全部行的全部版本-甚至当前版本。HBase里面TTL时间时区是UTC。
  • Cell
    A {row, column, version}元组就是HBase中的一个Cell。Cell的内容是不可分割的字节数组。
  • 字节模式存储
  • 倒序时间戳
    一个数据库处理的通常问题是找到最近版本的值。采用倒序时间戳作为键的一部分可以对此特定情况有很大帮助。也在Tom White的Hadoop书籍的HBase章节能找到:The Definitive Guide(O’Reilly),该技术包含追加(Long.MAX_VALUE-timestamp)到key的后面,如[key][reverse_timestamp]
    表内[key]的最近的值可以用[key]进行Scan找到并获取第一个记录。由于HBase行键是排序的,该键排在任何比它老的行键的前面,所以必然是第一个。

数据模型

简单来说,应用程序是以表的方式在HBase存储数据的。表是由行和列构成的,所有的列是从属于某一个列族的。行和列的交叉点称之为cell,cell是版本化的。cell的内容是不可分割的字节数组。
表的行键也是一段字节数组,所以任何东西都可以保存进去,不论是字符串或者数字。HBase的表是按key排序的,排序方式只针对字节的。所有的表都必须要有主键-key。

概念视图

下面是根据BigTable论文稍加修改的例子。有一个名为webtable的表,包含两个列族:contents和anchor。在这个例子里面,anchor有两个列(anchor:cssnsi.com, anchor:my.look.ca),contents仅有一列(contents:html)
列名
一个列名是由它的列族前缀和修饰符(qualifier)连接而成。例如列contents:html是列族contents加冒号(:)加修饰符html组成的。
Table webtable

Row Key Time Stamp ColumnFamily contents ColumnFamily anchor
“com.cnn.www” t9 anchor:cnnsi.com = “CNN”
“com.cnn.www” t8 anchor:my.look.ca = “CNN.com”
“com.cnn.www” t6 contents:html = "<html>..."
“com.cnn.www” t5 contents:html = "<html>..."
“com.cnn.www” t3 contents:html = "<html>..."

物理视图

尽管在概念视图里,表可以被看成是一个稀疏的行的集合。但在物理上,它的是区分列族存储的。新的columns可以不经过声明直接加入一个列族。
Table ColumnFamily anchor

Row Key Time Stamp Column Family anchor
“com.cnn.www” t9 anchor:cnnsi.com = “CNN”
“com.cnn.www” t8 anchor:my.look.ca = “CNN.com”

Table ColumnFamily contents

Row Key Time Stamp ColumnFamily “contents:”
“com.cnn.www” t6 contents:html = "<html>..."
“com.cnn.www” t5 contents:html = "<html>..."
“com.cnn.www” t3 contents:html = "<html>..."

值得注意的是在上面的概念视图中空白cell在物理上是不存储的,因为根本没有必要存储。因此若一个请求为要获取t8时间的contents:html,他的结果就是空。相似的,若请求为获取t9时间的anchor:my.look.ca,结果也是空。但是,如果不指明时间,将会返回最新时间的行,每个最新的都会返回。例如,如果请求为获取行键为”com.cnn.www”,没有指明时间戳的话,活动的结果是t6下的contents:html,t9下的anchor:cnnsi.com和t8下anchor:my.look.ca。
For more information about the internals of how HBase stores data, see Section 9.7, “Regions”.

数据模型操作

四个主要的数据模型操作是Get、Put、Scan和Delete,通过HTable实例进行操作。

  • Put
    要想覆盖一个现有的值,就意味着你的row-key,column和版本必须完全相等。
  • Delete
    通过Table.delete,从一个表中删除一行。
    HBase不会修改数据,所以删除时通过创建称之为墓碑(tombstones)标记。这些墓碑以及被删除的值在执行主紧缩是被清理。有三种不同类型的内部删除标记:
    1、Delete: 删除列的指定版本。
    2、Delete column: 删除列的所有版本。
    3、Delete family: 删除特定列族所有列
    当删除一行,HBase内部对每个列族创建墓碑(非每个单独列)。
    删除操作的实现是创建一个墓碑标记。例如,我们想要删除一个版本,或者默认是currentTimeMillis。就意味着“删除比这个版本更早的所有版本”。HBase不会去改那些数据,数据不会立即从文件中删除。他使用删除标记来屏蔽掉这些值。

版本

一个{row, column, version}元组是HBase中的一个单元(Cell)。但是有可能会有很多单元的行和列是相同的,可以使用版本来区分不同的单元。
row key和column key是用字节数组表示的,version则是用一个长整型表示。这个long的值使用java.util.Date.getTime()或者System.currentTimeMillis()产生的。这就意味着他的含义是“当前时间和1970-01-01 UTC的时间差,单位毫秒。”
在HBase中,版本是按倒序排列的,因此当读取这个文件的时候,最先找到的是最近的版本。
有些人不是很理解HBase单元(cell)的意思。一个常见的问题是:
如果有多个包含版本写操作同时发起,HBase会保存全部还是会保持最新的一个?答:保存全部,但是如果不指定版本获取只会获取到最新的那个。
可以发起包含版本的写操作,但是他们的版本顺序和操作顺序相反是否可以?答:可以

你可能感兴趣的:(HBase简单介绍)