HBase基础

HBase的读写流程设计

  1. 写数据:先预写日式WAL,和写入内容MemStore。WAL用来在节点宕机后恢复写入的数据。在MemStore写满后会写入磁盘,生成一个新的HFile,一旦写入不会再修改。一个列族有一个MemStore,一个列族有多个HFile。
  2. 读数据:每个列族有自己的BlockCache,用来在内存中缓存从HFile读入的数据,采用LRU算法淘汰数据。读数据时,先从MemStore中尝试读取修改的数据,然后检查BlockCache缓存,最后才访问HFile。
  3. 删除数据:先给数据打上删除标记,HFile在大合并中才真正删除掉这些数据。

数据坐标

如何准确的定位一个数据:
rowKey -> column family -> column qualifier -> versin -> value

HBase和关系数据库的设计思想的区别

HBase是一种键-值型数据库,key由rowKey -> column family -> column qualifier -> versin这些元素共同组成。

关系型数据库每个表只有两个维度,通过id和属性名可以得到相应的值。

数据库是用来存储事物的载体,关系数据库的局限在于从两个维度描述事物的属性,它可以方便的展现事物的一级属性,但是想要表现事物的多层级属性却不容易。如一个对象:

{
    "name":{
        "firstName":"Si",
        "lastName":"Li"
    },
    "age":10
}

在关系数据库中存储这样一个对象,要么将属性都提升为一级属性,要么在name属性中存储一个json数据,要么另起一个表,专门存储name的数据,并且通过name的id来关联数据间的关系。

而HBase则是一个四维的表,描述事物的能力更强,上述问题只要建立一个name的列族就可以解决。

像这种key-value型数据库,key可以描述无限维度的属性层级,可以更方便的描述事物,似乎是将来数据存储发展的趋势。

回过头来看关系数据库,虽然每个表只有两个维度,但可以通过表之间的关系来建立高维度属性来描述事物。从这个角度来看,关系型数据库反而道出了事物的本质。

面型列编程

一般情况下,现有数据的逻辑模型,然后物理模型根据逻辑模型进行设计和优化。而在HBase中,需要逆向思考,由于HBase中数据的物理存储遵循一定的规则,利用好这些规则来设计逻辑模型,可以大大的提高使用数据的效率。

HBase的各层级的key都是有序排列的,从row key到qualifier按照字节递增排列,而version则按照递减顺序排列。

HBase在一行记录里,如果某列没数据,则不会进行存储,不会占用存储空间,所以说是面向列编程。每行数据的每个列族可能会有多个HFile,但是一个列族的数据一定要在同一个物理存储中。

HBase不满足ACID

  1. 对于每行的操作,是原子的。
  2. 对于多行的操作,不是原子的。
  3. 扫描并不是对某一时刻的数据快照的读取,如果某行数据被扫描到前有变更,则读取的数据是变更后的数据。

Hadoop Mapreduce运行原理

工作过程:
map: 负责转化数据,将key1、value1输入转化key2、value2输出。
shuffle: 数据按照key分组、排序等。
reduce: 对一个key下的所有值进行处理,产生最后结果。

JobTracker: 负责调度、监控mapreduce任务。
TaskTracker: 负责实际的运行map或reduce任务。

HBase的分布式结构

一个表被分为多个region。RegionServer运行在HDFS系统之上,是HDFS的客户端,负责管理多个region。

如何定位region?-ROOT-.META.是两个特殊的表,它们也放在region中。-ROOT-表只在一个region中,.META.表则可能被分到多个region中。整个定位的过程如一个3层分布式B+树:

  1. ZooKeeper管理了表的-ROOT-的信息。
  2. 先在-ROOT-中查找,定位拥有该数据信息的.META.的region。
  3. 从.META.的region中的信息可以定位到数据在哪一个RegionServer里。

Mapreduce与HBase

HBase既可以做Mapreduce的数据源,也可以作为数据目的地。

如何在Mapreduce中做联结操作

对于不同表中的数据,通过rowKey将相关数据联结起来的操作对于非关系型数据库HBase来说并非易事。

在Mapreduce中可以有以下3种联结的实现方式:

  1. 在reduce侧做联结。将相同rowKey的数据在reduce任务上进行联结,需要在map和reduce之间做数据洗牌和排序,有很大的IO开销。
  2. 在map侧联结。将两个表中,数量小的表缓存在map节点中,map任务在拿到关联键后从缓存中读取相应的值,结合后进行发射。
  3. 在map中读取HBase。一个表作为mapreduce的数据源,在map任务中从HBase读取另一个表中相关联的数据。

HBase的可用性

可用性不是一个二元特性,即不是非此即彼的,而是一种程度上的模糊属性。HBase是高可用的,在RegionServer发生故障时,它管理的数据会切换到其它的RegionServer节点上。

单一命名空间。HBase把数据存储在一个文件系统上,一个RegionServer的读写数据可以为其它所有RegionServer读写。所以当一个RegionServer宕机时,其它RegionServer可以及时的接替它的任务。

HBase进阶

如何建模来充分发挥HBase的能力

  • HBase虽然号称是无模式的数据库,但是提前设计好数据的存储schema可以更好的发挥HBase的性能。
  • 列族一般要提前定义好,尽量少的改动。而列可以动态的增减,列即数据。
  • HBase没有跨行实务的概念。
  • 同一列族的数据在物理上是放在一起的,在列族中找到某一个列的大体过程是一个二分查找。所以,访问宽行要比窄行开销大。

精细的描述所需数据带来的收益

  • 行键:获取指定行的数据,该行下的所有相关HFile都会被读取。
  • 列族:进一步缩小读取HFile范围,只读相关的HFile。
  • 列限定符:不会进一步限定列族的范围,但会减少返回数据的网络占用。
  • 时间戳:进一步减少返回数据量。

反规范化

规范化是关系型数据库中的概念,指将每个表指保存自己关心的核心数据,其它的数据通过键来关联,通过join来查询多个表中的数据,尽量的避免同一份数据出现在两个地方,避免数据的不一致性。

反规范化是HBase中的概念,指行中可以冗余部分其它表的数据,以方便读取。

规范化是写优化,反规范化是读优化。

从关系型数据库到非关系型数据库

谨慎的将现有的系统从关系型数据库迁移到非关系型数据库,有时候付出的代价远比你得到的收益要高。

  • 实体

    • 关系型、非关系型数据库都通过表存储实体。
  • 属性

    • 识别属性(可以唯一的确定一条数据)在关系数据库中作为主键,在HBase中作为rowKey。非识别属性在HBase中对应列限定符。
  • 联系

    • 关系型数据库通过外键,或者关系表来刻画数据之间的关系。而HBase中没有这种限制,只能在应用中实现数据关系的代码。
参考《HBase实战》

你可能感兴趣的:(hbase,java)