初识HBase(一些HBase学习笔记)

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/u010287342/article/details/85406511

HBase从Google的bigtable论文发展而来,遵循着Key/value键值对、列存储模型。
Rowkey,一些地方翻译为行健,在HBase中用来唯一标识表中一行记录,不存在两行Rowkey一致的记录,且只能通过Rowkey进行行的查询,不存在其他列作为查询/过滤条件的方式(可以通过对其他列值和对应的rowkey建一个索引表进行二级查询来实现)。
Rowkey在内部是以一个字节数组的方式进行存储,每一行数据根据rowkey的字段排序顺序进行排列存储。
Rowkey行键的设计十分重要:因为每一行的查找离不开对行健的检索,而插入数据时需根据行健值进行寻址,故行健的设计影响行的存储和查询速度。当行健设计没有考虑足够多的情况时,可能会出现多行记录的Rowkey一致的情况,一般情况下HBase会将此种情况视为同一行的不同(时间)版本来存储记录,若重复记录数超过最大保存版本数时,会使得有用的数据丢失。最直接的解决办法就是通过修改每列保存的最大版本数来防止数据丢失,但此种办法并不万全。一是每一列重复版本数(因为HBase是列存储结构,所以版本是针对每一列的,并不是针对一行,故当我们查询某一行时,系统默认给出每一列最新版本的值,有的列版本可能是1有的可能是3有的可能是…)是多少不能准确预估,二是由于表记录是根据行健的值的字典排列顺序分配存储位置的,大量相同的行健或者具有相同的行健前缀的情况,比如用户数据都是以“user”为前缀,则会导致大量记录挤压在某一个节点上,造成I/O压力,有违分布式的初衷。
实践见真知:为了便于查询订单信息,工程师在HBase中构建了订单信息库,一开始采用了“订单号+时间”的行健组合方式,由于订单号为顺序产生的id,一开始插入数据时,数据会一直往某一或者某几个节点写入,这几个节点的Region分裂情况十分频繁,而其他节点则比较空闲,运营时间一长就会出现节点宕机甚至由一个节点引起的整个集群雪崩式宕机的情况。解决方案:“hash(订单号)+创建时间”。单纯以订单号或者订单创建时间作为前缀都不好,使用hash(订单号)的方式可以得到打散Rowkey分布的效果,加上创建时间是为了满足通过创建时间来查询,若订单号出现重号也能提高唯一性,如果有需要通过其他列值来查询,可以采用“hash(订单id)+列1+列2…”的方式,但要注意Rowkey过长的问题,Rowkey过长也会制衡行的写入和扫描效率。
Region,即表的物理分区,HBase中一个表会有一个到多个Region,通常一个集群内每个Region的大小是固定的,便于内部根据当前写入位置所在的Region的大小来决定是否一分为二(分裂),是均衡负载的基本单元,每个Region存储着Rowkey排序连续的一批数据且分布在指定一个RegionServer上。
稀疏矩阵,HBase表中行是原子的可以加锁,但是每一行拥有的列修饰符、列数量不尽相同,每行不需要执行严格的列定义,即所谓“Schema-less”。因为HBase中不会存储空值,所以当某一行某列为空时,元数据不会记录该列,从而形成稀疏矩阵。
ColumnFamily,列簇/列族,一个或者多个列组成一个列族(下称CF),因CF需要在建表时定义好且无法在建表后修改,故每行会有相同的CF定义、每个表至少拥有一个CF,但每个CF中实际拥有的列因行而异(即稀疏矩阵)。
列修饰符,列不需要提前声明,只需要在插入数据时指定数据值对应的列修饰符即可,同时需要指定该列所属的CF(空值不做插入操作),故CF和列修饰符是一对多关系,HBase内部通过CF找到列,同一CF下所有列数据物理上会存储到一起,同一CF下的列也是顺序排列的。
关于建表时CF指定多少的问题。HBase表设计时CF量不宜过多,需要从物理存储、I/O方式来说明(以下说明参考自博客 https://my.oschina.net/nk2011/blog/796715) :一个HBase表含有一个到多个Region,每个Region含有一个到多个HBaseStore存储块,每个HBaseStore自带一个元数据记录和多个数据文件StoreFile/HFile,通常一个CF会对应一个HBaseStrore,Region大小达到阀值会自动分裂,一个表存在多列簇时:
A.一个Region中含有多个HBaseStore,如果每个CF中数据量分布不均匀,如CF1为100w,CF2为2w,则单个Region中的CF2占比不高,随着表数据量增长Region不断分裂,如若需要批量查询CF2的数据时,可能需要跨越(比CF1)更多个Region去查询,增加了寻址压力,降低查询效率;
B.多个CF的情况下,每个Region下需要记录多个元数据,由于元数据是实时加载到内存的,这样会增加节点RegionServer的内存压力;
C.HBase以Region为单位进行缓存刷新和压缩操作,CF越多,需要对单个Region的刷新和压缩操作次数越多,增加I/O压力。
版本,同一cell(定位数据的最小单位)根据插入的时间先后,可以保存多个版本的值(历史轨迹的留存),可通过对应的列修饰符指定需要保存的版本上限数,一般保留5个历史版本,可通过指定版本号查询历史记录。如果查询时没指定所要查询的版本号,HBase默认返回最新的版本。RDBMS中的表是二维的,而在bigdata存储模型上,可以看作是三维的(行+列+时间)。
至此,我们已经可以清晰看到,在HBase某个表中,通过行(Rowkey行键)、CF列簇、列修饰符和版本号才能唯一确定一个cell中的data(四维结构)。Cell是最小确定的数据单元,cell中的数据不需要指定对应的数据类型,统一以字节码的形式存储。

Enable修饰符,修饰某一表,使之有效可用可访问。
HBase中不能使用join操作,一般通过设置大宽表来实现数据串联。
通常在hadoop存储中,对数据离线批处理是有利的,但在实时查询时显得臃肿。在HBase中通过Key-Value键值对来支持实时查询,而通过Map-Reduce来支持批处理。
End

猜你喜欢

转载自blog.csdn.net/u010287342/article/details/85406511
今日推荐