HBase的表结构设计

HBase的表结构设计

1 名称空间

1.1 说明
  • 在一个项目中,需要使用HBase保存多张表,这些表会按照业务域来划分

  • 为了方便管理,不同的业务域以名称空间namespace来划分,这样管理起来会更加容易

  • 类似于Hive中的数据库,不同的数据库下可以放不同类型的表

  • HBase默认的名称空间是default,默认情况下,创建表时表都将创建在 default 名称空间下

  • HBase中还有一个命名空间hbase,用于存放系统的内建表(namespace、meta)

1.2 语法

创建命名空间

create_namespace 'MOMO_CHAT'

查看命名空间列表

list_namespace

查看命名空间

describe_namespace 'MOMO_CHAT'

命名空间创建表

注意:带有命名空间的表,使用冒号将命名空间和表名连接到一起。

#语法
create '名称空间:表名','列簇'...

#示例:
#在MOMO_CHAT命名空间下创建名为:MSG的表,该表包含一个名为C1的列蔟。
create 'MOMO_CHAT:MSG','C1'     

删除命名空间

  • 删除命名空间,命名空间中必须没有表,如果命名空间中有表,是无法删除的
drop_namespace 'MOMO_CHAT'

2 列蔟设计

  • HBase列蔟的数量应该越少越好

  • 两个及以上的列蔟HBase性能并不是很好

  • 一个列蔟所存储的数据达到flush的阈值时,表中所有列蔟将同时进行flush操作

  • 这将带来不必要的I/O开销,列蔟越多,对性能影响越大

  • 项目中我们一般只设计一个列蔟

3 版本设计

  • HBase 通过 HColumnDescriptor 为每个列族配置要存储的最大行数版本。最大版本的默认值为1。这是一个重要的参数,因为如数据模型部分所述,HBase 也没有覆盖行的值,而是按时间(和限定符)存储不同的值。在重要的压缩过程中删除多余的版本。最大版本的数量可能需要根据应用程序需求增加或减少。
  • 不建议将最高版本数设置为极高的级别(例如,数百个或更多),除非这些旧值对您非常重要,因为这会大大增加 StoreFile 大小

我们可以通过命令来查看一下版本的信息:

通过以下输出可以看到:

  • 版本是相对于列蔟而言

  • 默认列蔟的版本数为1

hbase(main):015:0> describe "MOMO_CHAT:MSG"
Table MOMO_CHAT:MSG is ENABLED                               
MOMO_CHAT:MSG                                                 
COLUMN FAMILIES DESCRIPTION                                   
{NAME => 'C1', VERSIONS => '1', EVICT_BLOCKS_ON_CLOSE => 'false', NEW_VERSION_BEHAVIOR => 'false', KEEP_DELETED_CELLS => 'FALSE', CACHE_DATA_ON_WRITE => 'false', DATA_BLOCK_ENCODING => 'NONE', TTL => 'FOREVER', MIN_VERSIONS => '0', REPLI
CATION_SCOPE => '0', BLOOMFILTER => 'ROW', CACHE_INDEX_ON_WRITE => 'false', IN_MEMORY => 'false', CACHE_BLOOMS_ON_WRITE => 'false', PREFETCH_BLOCKS_ON_OPEN => 'false', COMPRESSION => 'NONE', BLOCKCACHE => 'true', BLOCKSIZE => '65536'}   
1 row(s)

4 数据压缩

4.1 压缩算法

在HBase可以使用多种压缩编码,包括LZO、SNAPPY、GZIP。只在硬盘压缩,内存中或者网络传输中没有压缩。

压缩算法压缩后占比压缩解压缩
GZIP13.4%21 MB/s118 MB/s
LZO20.5%135 MB/s410 MB/s
Zippy/Snappy22.2%172 MB/s409 MB/s
  • GZIP的压缩率最高,但是其实CPU密集型的,对CPU的消耗比其他算法要多,压缩和解压速度也慢;

  • LZO的压缩率居中,比GZIP要低一些,但是压缩和解压速度明显要比GZIP快很多,其中解压速度快的更多;

  • Zippy/Snappy的压缩率最低,而压缩和解压速度要稍微比LZO要快一些

4.2 查看表数据压缩方式

通过以下输出可以看出COMPRESSION => 'NONE',HBase创建表默认是没有指定压缩算法的

hbase(main):015:0> describe "MOMO_CHAT:MSG"
Table MOMO_CHAT:MSG is ENABLED                                    
MOMO_CHAT:MSG                                                   
COLUMN FAMILIES DESCRIPTION                                     
{NAME => 'C1', VERSIONS => '1', EVICT_BLOCKS_ON_CLOSE => 'false', NEW_VERSION_BEHAVIOR => 'false', KEEP_DELETED_CELLS => 'FALSE', CACHE_DATA_ON_WRITE => 'false', DATA_BLOCK_ENCODING => 'NONE', TTL => 'FOREVER', MIN_VERSIONS => '0', REPLI
CATION_SCOPE => '0', BLOOMFILTER => 'ROW', CACHE_INDEX_ON_WRITE => 'false', IN_MEMORY => 'false', CACHE_BLOOMS_ON_WRITE => 'false', PREFETCH_BLOCKS_ON_OPEN => 'false', COMPRESSION => 'NONE', BLOCKCACHE => 'true', BLOCKSIZE => '65536'}   
1 row(s)
4.3 设置数据压缩

创建新的表,并指定数据压缩算法

create "MOMO_CHAT:MSG", {NAME => "C1", COMPRESSION => "GZ"}

修改已有的表,并指定数据压缩算法

alter "MOMO_CHAT:MSG", {NAME => "C1", COMPRESSION => "GZ"}

5 ROWKEY设计原则

5.1 HBase官方的设计原则
1. 避免使用递增行键/时序数据

如果ROWKEY设计的都是按照顺序递增(例如:时间戳),这样会有很多的数据写入时,负载都在一台机器上。我们尽量应当将写入大压力均衡到各个RegionServer

2. 避免ROWKEY和列的长度过大
  • 在HBase中,要访问一个Cell(单元格),需要有ROWKEY、列蔟、列名,如果ROWKEY、列名太大,就会占用较大内存空间。所以ROWKEY和列的长度应该尽量短小

  • ROWKEY的最大长度是64KB,建议越短越好

3. 使用long等类型比String类型更省空间

long类型为8个字节,8个字节可以保存非常大的无符号整数,例如:18446744073709551615。如果是字符串,是按照一个字节一个字符方式保存,需要快3倍的字节数存储。

4. ROWKEY唯一性
  • l设计ROWKEY时,必须保证RowKey的唯一性

  • 由于在HBase中数据存储是Key-Value形式,若向HBase中同一张表插入相同RowKey的数据,则原先存在的数据会被新的数据覆盖。

5.2 避免数据热点
  • 热点是指大量的客户端(client)直接访问集群的一个或者几个节点(可能是读、也可能是写)

  • 大量地访问量可能会使得某个服务器节点超出承受能力,导致整个RegionServer的性能下降,其他的Region也会受影响

1、 预分区
  • 默认情况,一个HBase的表只有一个Region,被托管在一个RegionServer中

  • 每个Region有两个重要的属性:Start Key、End Key,表示这个Region维护的ROWKEY范围

  • 如果只有一个Region,那么Start Key、End Key都是空的,没有边界。所有的数据都会放在这个Region中,但当数据越来越大时,会将Region分裂,取一个Mid Key来分裂成两个Region

  • 预分区个数 = 节点的倍数。默认Region的大小为10G,假设我们预估1年下来的大小为10T,则10000G / 10G = 1000个Region,所以,我们可以预设为1000个Region,这样,1000个Region将均衡地分布在各个节点上

指定 start key、end key来分区

#语法
create ‘表名‘,’列簇‘,SPLITS=>[分区区间]
#示例,第一个shell命令 创建表的时候,定义了5个分区
hbase> create 'ns1:t1', 'f1', SPLITS => ['10', '20', '30', '40']
hbase> create 't1', 'f1', SPLITS => ['10', '20', '30', '40']
hbase> create 't1', 'f1', SPLITS_FILE => 'splits.txt', OWNER => 'johndoe'

指定分区数量、分区策略

分区策略:

HexStringSplitROWKEY是十六进制的字符串作为前缀的
DecimalStringSplitROWKEY是10进制数字字符串作为前缀的
UniformSplitROWKEY前缀完全随机
#语法
hbase> create 't1', 'f1', {NUMREGIONS => 15, SPLITALGO => 'HexStringSplit'}
2、 ROWKEY避免热点设计
  1. 反转策略
  • 如果设计出的ROWKEY在数据分布上不均匀,但ROWKEY尾部的数据却呈现出了良好的随机性,可以考虑将ROWKEY的翻转,或者直接将尾部的bytes提前到ROWKEY的开头。

  • 反转策略可以使ROWKEY随机分布,但是牺牲了ROWKEY的有序性

  • 缺点:利于Get操作,但不利于Scan操作,因为数据在原ROWKEY上的自然顺序已经被打乱

  1. 加盐策略
  • Salting(加盐)的原理是在原ROWKEY的前面添加固定长度的随机数,也就是给ROWKEY分配一个随机前缀使它和之间的ROWKEY的开头不同

  • 随机数能保障数据在所有Regions间的负载均衡

  • 缺点:因为添加的是随机数,基于原ROWKEY查询时无法知道随机数是什么,那样在查询的时候就需要去各个可能的Regions中查找,加盐对比读取是无力的

  1. 哈希策略
  • 基于 ROWKEY的完整或部分数据进行 Hash,而后将Hashing后的值完整替换或部分替换原ROWKEY的前缀部分

  • 这里说的 hash 包含 MD5、sha1、sha256 或 sha512 等算法

  • 缺点:Hashing 也不利于 Scan,因为打乱了原RowKey的自然顺序

  • 1
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值