Hbase的表是由行和列构成的,所有的列是从属于某一个列族的。行和列的交叉点称之为cell,cell是版本化的。cell的内容是不可分割的字节数组。
概念视图
下面是根据BigTable 论文稍加修改的例子。 有一个名为webtable
的表,包含两个列族:contents
和anchor
.在这个例子里面,anchor
有两个列 (anchor:cssnsi.com
, anchor:my.look.ca
),contents
仅有一列(contents:html
)
列名
一个列名是由它的列族前缀和修饰符(qualifier)连接而成。例如列contents:html是列族 contents
加冒号(:
)加 修饰符 html
组成的。
表 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>..." |
物理视图
尽管在概念视图里,表可以被看成是一个稀疏的行的集合。但在物理上,它是分列族存储的。我们在设计Hbase表时可以设计两个列族,一个用来存储经常被用到的列,一个用来存储不经常用的列,columns可以不经过声明直接加入一个列族.
Table 5.2. 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 5.3. 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在物理上是不存储的,因为根本没有必要存储。
5.3. 表
表是在schema声明的时候定义的。
5.4. 行
行键是不可分割的字节数组。行是按字典排序由低到高存储在表中的。一个空的数组是用来标识表空间的起始或者结尾。
5.5. 列族
在HBase是列族一些列的集合。一个列族所有列成员是有着相同的前缀。比如,列courses:history 和 courses:math都是 列族 courses的成员.冒号(:)是列族的分隔符,用来区分前缀和列名。column 前缀必须是可打印的字符,剩下的部分(称为qualify),可以由任意字节数组组成。列族必须在表建立的时候声明。column就不需要了,随时可以新建。
在物理上,一个的列族成员在文件系统上都是存储在一起。因为存储优化都是针对列族级别的,这就意味着,一个column family的所有成员的是用相同的方式访问的。
5.6. Cells
A {row, column, version} 元组就是一个HBase中的一个 cell
。Cell的内容是不可分割的字节数组。
5.7. 数据模型操作
四个主要的数据模型操作是 Get, Put, Scan, 和 Delete. 通过 HTable 实例进行操作.
5.9. 排序
所有数据模型操作 HBase 返回排序的数据。先是行,再是列族,然后是列修饰(column qualifier), 最后是时间戳(反向排序,所以最新的在前).
5.10. 列的元数据
对列族,没有内部的KeyValue之外的元数据保存。这样,HBase不仅在一行中支持很多列,而且支持行之间不同的列。 由你自己负责跟踪列名。
唯一获取列族的完整列名的方法是处理所有行。HBase内部保存数据更多信息,请参考 Section 9.7.5.4, “KeyValue”.
5.11. 联合查询(Join)
HBase是否支持联合是一个网上常问问题。简单来说 : 不支持。至少不想传统RDBMS那样支持(如 SQL中带 equi-joins 或 outer-joins). 正如本章描述的,读数据模型是 Get 和 Scan.
但并不表示等价联合不能在应用程序中支持,只是必须自己做。 两种方法,要么指示要写到HBase的数据,要么查询表并在应用或MapReduce代码中做联合(如 RDBMS所展示,有几种步骤来实现,依赖于表的大小。如 nested loops vs. hash-joins). 哪个更好?依赖于你准备做什么,所以没有一个单一的回答适合所有方面。
5.12. ACID
原子性:
1.hbase修改某一行都是原子性的。对某一行的操作要么全部执行成功,要么全部执行失败,不存在部分执行成功或者部分失败的情况。
2.对一行的多个列族进行操作也是这样,都是原子性的,在一次操作多个列族的时候不可能一个成功宁外一个失败,要么全部成功要么全部失败。
3.hbase对多行进行的操作不是原子性的。
4.The checkAndPut API 有点像很多架构中的compareAndSet (CAS) cas操作。
5.hbase的操作不会交叉进行,例如一个写操作"a=1,b=1,c=1",另外一个是 "a=2,b=2,c=2" 结果将会是"a=1,b=1,c=1" or "a=2,b=2,c=2" 不会有像"a=1,b=2,c=1".这样的结果。如果是批操作有可能会不同。
一致性和隔离性
扫描的一致性
1.任何通过scan在某时返回的将是同一个视图;
2.scan操作返回在进行scan操作的时候的数据情况;
3.scan必须包括所有数据扫描前写的内容。
这些像大家熟悉的关系型数据库的read commit隔离级别相似。
scan操作有可能看到它后面提交的数据,只要是提交的数据在scan操作构建完成前。
Visibility
1.当一个客户端改变数据成功,这些改变将会立即对其他连接Hbase的客户端可见。
2.
3.
Durability
1.所有可视化的数据都是持久化了的数据。也就是说,Hbase的读永远也不会返回没有被持久化的数据。
2.所有返回 "success" code的将会被持久化;
3.任何返回"failure" code 的将不会被持久化;
4.所有失败的场景将不会影响Hbase数据库。
摘自:http://abloz.com/hbase/book.html#conceptual.view