设计重点

HBase模式的重点有两个:Rowkey 和 Column Family

Rowkey的设计

Rowkey设计是HBase模式设计中最重要的事情

1、HBase数据基于Rowkey有序存储。Rowkey是HBase表的唯一索引,借助Rowkey对HBase表的访问能实现高效的二分查找,非Rowkey的访问只能通过全表扫描实现。

2、region根据有序的Rowkey进行划分

Rowkey的一个经典的设计是:id+时间戳,这种设计充分利用了HBase表中行键有序存储的特性。这种设计可以将id相关数据聚合在一起。

Rowkey要尽量均匀分布

要充分利用散列算法将Rowkey均匀分散开来,这样各个region存储的rowkey基本均衡,避免了个别region承担过多的读写负载

Rowkey的长度尽量短

1、时间尽量用long来表示,而不是字符串

2、尽量使用编码压缩

关于Join

HBase不支持表间连接!表间连接一般通过反范式设计,即冗余存储来实现。

列族设计

HBase数据表对行进行水平分片得到region。region单独完整地存储(HDFS冗余备份对上层的HBase不可见)在某台服务器上。region按列族进行垂直分片得到store,每一个列族对应一个store。store数据不断刷写得到HFile,最后HFile落实到HDFS中存储。

hbase主键查询 hbase主键设计_数据

列族设计原则如下:

1、在满足业务需求的情况下,列族越少越好,这样可以将flush和compaction操作限制在一个region里面进行,这样可以减少不必要的I/O负载。

2、不同列族的数据要均衡

打个比方,T1表有两个列族F1、F2。F1有10w条数据,F2有1ww条数据。这样F1将会稀疏地分散到很多地region中,导致F1地扫描效率降低。这是数据条目地均衡

再打个比方,T1表有两个列族F1、F2。F1和F2在数据条目上是均衡的。可是F1每条数据的大小是1K,F2每条数据的大小是1G,那么F1依然会稀疏地分散到很多地region中,导致F1地扫描效率降低。

典型案例剖析:图书馆借书

核心业务需求:查询某同学在图书馆借了那些书,查询某本书是被谁借走了

RDBMS设计

学生表:

PK

stu_name

stu_num

stu_info

 

 

 

 

 

 

 

 

图书表

PK

book_name

book_num

book_info

 

 

 

 

 

 

 

 

借书关系

PK

FK:stu_PK

FK:book_PK

 

 

 

 

 

 

1、某同学借了那些书

1.1、根据学生学号,查到行数据(遍历学生表,如果在学号上建立了索引可以提高查询效率),取出stu_PK

1.2、根据stu_PK,查出对应的数据集(遍历借书关系表,如果在FK:stu_PK上建立了索引可以提高查询效率)

1.3、根据1.2查出的数据集取出book_PK集,到图书表中匹配,图书行数据(双遍历,取出的book_PK集*图书表book_PK,由于图书表book_PK有索引,速度会加快)

2、某书被谁借走了

跟“某同学借了那些书”差不多

HBase设计

本文暂且采取宽表设计,也可采取高表设计

学生借书表

Rowkey=stu_num

borrow_info

stu_name

stu_info

book_num1

book_num2

...

book_numN

 

 

 

1

0

1

0

图书借阅表

Rowkey=book_num

borrowed_info

book_name

book_info

stu_num1

stu_num2

...

stu_numN

 

 

 

1

0

0

0

这种设计更为直接,借书关系实际上在两张表里面都有存储。这样的冗余存储解决了HBase不支持join的缺陷。这种冗余存储方式在还书的时候出现了麻烦。理想情况下,还书的时候,希望学生借书表里面borrow:book_num*里面的计数器要修改,同时图书借阅表中stu_num*中的计数器也要修改。坑爹的是HBase又不支持跨表/行事务。这样极容易导致数据库的不一致性!其实不一致性并不可怕,只要不一致性可以得到合理的解释,HBase仍然能在不一致的情况下正确工作。我们下面结合这个例子来具体分析下:

首先,我们在还书的时候肯定要发出两条修改命令。这两条命令各自是原子的,但是整体不是原子的。这两条命令在大多数时候是可以正确运行的。不一致情况如下:

1、两条命令都成功,但是时间间隔有点长,在此间隔时间内数据库状态时不一致的

2、其中一条命令失败,此后数据库状态都是不一致的

还书的意义在于

1、证明学生名下已经没有这本书了

2、看看此书是否被占用,即是否可以被借出

我们看看第一点,证明学生名下有无这本书。这个显然要通过学生借书表来体现。

我们看看第二点,看看此书是否可以被借出。当一个学生从图书馆的书架上拿着这本书来找管理员借阅的时候,其实已经证明了书是可以借阅的。何须查询数据库,然后告诉学生可否被借阅?

这样,我们就定义不一致数据的解释:是否还书,以学生借书表为准!这样,在还书的时候,虽然还是两条修改命令都发出,但是还书操作以学生借书表是否成功修改为准。判断是否还书也以学生借书表为准!如果出现不一致状态,以学生借书表为准!