首页
学习
活动
专区
工具
TVP
发布
精选内容/技术社群/优惠产品,尽在小程序
立即前往

HBase之高级用法

【导读:数据是二十一世纪的石油,蕴含巨大价值,这是·情报通·大数据技术系列第[47]篇文章,欢迎阅读和收藏】

1基本概念

本文更深入探讨 HBase 存储设计架构中的各种问题:行键设计、高表与宽表的选择等。

2行键设计

在 Hbase 中有两类基本的键结构:行键和列键,

·列键:包括了列族名和列限定符,定位到列的索引

·行健:相当于关系型数据库中的主键,通过行键得到逻辑布局中一行的所有列

HBase表实际存储的时候每个列族的以单独的文件存储的,不同列族的单元格绝对不会出现在同一个 StoreFile 中 ,同时, HBase 也不会存储值为空的单元格。每个单元格在实际存储的时候也保存了行健和列键,所以每个单元格都单独存储了它在表中所处位置的关键信息,同一个单元格的不同版本被单独存储为连续的单元格,单元格按照时间戳降序排列,所以默认读取的是最新的单元格数据。同一列族的单元格在存储的时候先按行健排序,当一行中有多个单元格的时候再按列键排序,同一单元格有多个版本的时候按时间戳排序。这种含有结构信息的整个单元格在 HBase 中叫做 KeyValue 。KeyValue 存储时先按行键排序,当一行有多个单元格是再按列键排序。

row key + column family + column qualifier + timestamp + value是 HFile 中数据排列依据。行键决定数据的读取维度或模式,如果需要额外的读取顺序,则可以给表添加格外的列族,用于存储其他读取顺序的索引。比如:对于收件箱应用,行键为 userID , data 列族存消息数据(列名为 messageID ,值为消息内容),而 idx 列族存索引(列为标示 + 消息主题,值为附加信息)。这样就可以在读取索引列族时,得到按主题有序的数据。

2.1行键设计原则

基本原则是尽量把查询的维度或信息存入行健中,因为这样筛选数据的效率最高。从表的形式看,主要有列少行多的高表和行多列少的宽表,一般情况下高表更有优势,因为 hbase 只能按行拆分。

防止数据过热:当时间序列类型的数据(行健为时间戳)写入时,数据集中在一个 region 中,很容易产生读写热点。解决办法有 :1) 添加 hash 前缀, 2 )字段交换或提升权重:即在行键中添加另外一个字段或交换杭建中多个字段的位置, 3 )随机化,比如对整个行健取 MD5 ,作为新的行健。以上方法顺序度的性能由高到低,而写入的速度由低到高。

Rowkey长度原则:Hbase 按单个行健 Rowkey 检索的效率是很高的,耗时在 1 毫秒以下,每秒钟可获取 1000~2000 条记录。Rowkey 是一个二进制码流, Rowkey 的长度被很多开发者建议说设计在 10~100 个字节,不过建议是越短越好,不要超过 16 个字节。原因如下:

( 1 )数据的持久化文件 HFile 中是按照 KeyValue 存储的,如果 Rowkey 过长比如 100 个字节, 1000 万列数据光 Rowkey 就要占用 100*1000 万 =10 亿个字节,将近 1G 数据,这会极大影响 HFile 的存储效率;

( 2 ) MemStore 将缓存部分数据到内存,如果 Rowkey 字段过长内存的有效利用率会降低,系统将无法缓存更多的数据,这会降低检索效率。因此 Rowkey 的字节长度越短越好。

( 3 )目前操作系统是都是 64 位系统,内存 8 字节对齐。控制在 16 个字节, 8 字节的整数倍利用操作系统的最佳特性。

Rowkey散列原则:如果 Rowkey 是按时间戳的方式递增,不要将时间放在二进制码的前面,建议将 Rowkey 的高位作为散列字段,由程序循环生成,低位放时间字段,这样将提高数据均衡分布在每个 Regionserver 实现负载均衡的几率。如果没有散列字段,首字段直接是时间信息将产生所有新数据都在一个 RegionServer 上堆积的热点现象,这样在做数据检索的时候负载将会集中在个别 RegionServer ,降低查询效率。

2.2设计举例

1、针对事务数据 Rowkey 设计

事务数据是带时间属性的,建议将时间信息存入到 Rowkey 中,这有助于提示查询检索速度。对于事务数据建议缺省就按天为数据建表,这样设计的好处是多方面的。按天分表后,时间信息就可以去掉日期部分只保留小时分钟毫秒,这样 4 个字节即可搞定。加上散列字段 2 个字节一共 6 个字节即可组成唯一 Rowkey 。如下图所示:

这样的设计从操作系统内存管理层面无法节省开销,因为 64 位操作系统是必须 8 字节对齐。但是对于持久化存储中 Rowkey 部分可以节省 25% 的开销。也许有人要问为什么不将时间字段以主机字节序保存,这样它也可以作为散列字段了。这是因为时间范围内的数据还是尽量保证连续,相同时间范围内的数据查找的概率很大,对查询检索有好的效果,因此使用独立的散列字段效果更好,对于某些应用,我们可以考虑利用散列字段全部或者部分来存储某些数据的字段信息,只要保证相同散列值在同一时间(毫秒)唯一。

2、针对统计数据 Rowkey 设计

统计数据也是带时间属性的,统计数据最小单位只会到分钟(到秒预统计就没意义了)。同时对于统计数据我们也缺省采用按天数据分表,这样设计的好处无需多说。按天分表后,时间信息只需要保留小时分钟,那么 0~1400 只需占用两个字节即可保存时间信息。由于统计数据某些维度数量非常庞大,因此需要 4 个字节作为序列字段,因此将散列字段同时作为序列字段使用也是 6 个字节组成唯一 Rowkey 。如下图所示:

同样这样的设计从操作系统内存管理层面无法节省开销,因为 64 位操作系统是必须 8 字节对齐。但是对于持久化存储中 Rowkey 部分可以节省 25% 的开销。预统计数据可能涉及到多次反复的重计算要求,需确保作废的数据能有效删除,同时不能影响散列的均衡效果,因此要特殊处理。

3、针对通用数据的 Rowkey 设计

通用数据采用自增序列作为唯一主键,用户可以选择按天建分表也可以选择单表模式。这种模式需要确保同时多个入库加载模块运行时散列字段(序列字段)的唯一性。可以考虑给不同的加载模块赋予唯一因子区别。设计结构如下图所示。

3高表与宽表的选择

宽表是指很多列较少行,即列多行少的表,一行中的数据量较大,行数少;高表是指很多行较少列,即行多列少,一行中的数据量较少,行数大。

在 HBase 中使用宽表、高表的优劣总结如下:

l查询性能:高表更好,因为查询条件都在 row key 中 , 是全局分布式索引的一部分。高表一行中的数据较少。所以查询缓存 BlockCache 能缓存更多的行,以行数为单位的吞吐量会更高。

l分片能力:高表分片粒度更细,各个分片的大小更均衡。因为高表一行的数据较少,宽表一行的数据较多。HBase 按行来分片。

l元数据开销:高表元数据开销更大。高表行多, row key 多,可能造成 region 数量也多, - root - 、 .meta 表数据量更大。过大的元数据开销,可能引起 HBase 集群的不稳定、 master 更大的负担(这方面后续再好好总结)。

l事务能力:宽表事务性更好。HBase 对一行的写入( Put )是有事务原子性的,一行的所有列要么全部写入成功,要么全部没有写入。但是多行的更新之间没有事务性保证。

l数据压缩比:如果我们对一行内的数据进行压缩,宽表能获得更高的压缩比。因为宽表中,一行的数据量较大,往往存在更多相似的二进制字节,有利于提高压缩比。通过压缩,缓解了宽表一行数据量太大,并导致分片大小不均匀的问题。查询时,我们根据 row key 找到压缩后的数据,进行解压缩。而且解压缩可以通过协处理器( coproesssor )在 HBase 服务器上做,而不是在业务应用的服务器上做,以充分应用 HBase 集群的 CPU 能力。

设计表时,可以不绝对追求高表、宽表,而是在两者之间做好 ** 平衡 ** 。根据查询模式,需要分布式索引、分片、 ** 有很高选择度 ** (即能据此查询条件迅速锁定很小范围的一些行)的查询用字段,应该放入 row key ;能够均匀地划分数据字节数的字段,也应该放入 row key ,作为分片的依据。选择度较低,并且不需要作为分片依据的查询用字段,放入 column family 和 column qualifier ,不放入 row key 。

4辅助索引

辅助索引是为了数据可以按主坐标(行键、列族和列限定符)之外的方式快速定位数据。解决方案有:

1)由客户端管理索引:维护数据表和辅助索引表两个表。当数据写入时,除了写入数据外,还要将数据表的行健写入索引表。这些操作全部由应用层客户端完成,很灵活,但是缺少事务特性,当数据写入成功而索引失败时两个表将不同步,可以采用定期修剪(如周期性的跑 mapreduce 任务来删除或增加不一致的条目)解决。

2)带索引的事务性 HBASE ( ITHBASE ):开源、扩展了 hbase ,主要增加保证所有辅助索引更新一致性的事务功能。同样需要数据表和辅助索引表两张表,跟客户端管理索引不同的是这些操作都在服务器端自动完成。缺点是独立于 hbase 发行,可能不支持某些版本的 hbase 。

3)带索引的 hbase :不同以上两种方式为每个索引单独建表存储,这种方式直接在内存存储索引。当 region 第一次被打开或者 memstore 被刷写到磁盘时,通过扫描整个 region 来建立索引。这种方式可能消耗大量的 IO 和时间资源,入侵性很强,在按照辅助索引定义的顺序查找时数据表上做的是随机查找,也存在 hbase 版本兼容问题;优点是数据时同步的不需要额外的事务支持,而且支持类型如 byte 等。

4)协处理器:使用协处理器框架提供的服务器端的钩子函数实现类似于 ITHBASE 和 IHBASE 的索引,但不需要替换任何服务器端类。协处理器为每个 region 载入索引层,并维护索引。

5搜索集成

满足用户使用任意关键字来搜索数据的需求,往往需要集成一个完整的搜索引擎。常见的方案是基于 Apache Lucene 的解决方案。以下是一系列的可行方法。

客户端管理:用 HBase 存储数据,同时用 MapReduce 任务建立索引,并且 Lucene 的后台存储用 HBase 。

Lucene:独立于 HBase 使用的 Lucene 解决方案。通过 MapReduce 建立索引, BuildTableIndex 类可以扫描整个表,并建立 Lucene 索引,存储在 HDFS 上

HBasene:直接在 HBase 内部建立搜索索引,同时为用户提供给 Lucene 的 API 。

协处理器:实现一个类似于基于 Lucene 的数据查询功能的数据表。

6事务

通常情况下,用户并不需要事务,因为范式化的数据模式能够被转化成单个表的存储,所以此时不需要事务的支持。如果用户还需要一致性的支持,有以下几种可选解决方案:

1)事务型 HBASE :ITHbase 有一些取代默认客户端类和服务器端类的扩展类,增加啦跨行甚至跨表的事务支持。每个 region 都保持了一个事务列表,从 beginTransaction 开始,到 commit 结束。每次读写操作有一个事务 ID ,保证不受其他事务影响。

2) Zookeeper :将 Zookeeper 作为一个事务来控制后端,利用 znode 实现分布式锁。

7布隆过滤器

布隆过滤器可以减少 I/O 操作的层面,但是消耗很大性能,默认不用。

布隆过滤器有两种:行级过滤器和行加列级的过滤器。

Bloom过滤器原理:当一个元素被加入集合时,通过 K 个散列函数将这个元素映射成一个位数组中的 K 个点,把它们置为 1 。检索时,我们只要看看这些点是不是都是 1 就(大约)知道集合中有没有它了:如果这些点有任何一个 0 ,则被检元素一定不在;如果都是 1 ,则被检元素很可能在。这就是布隆过滤器的基本思想。

优点:相比于其它的数据结构,布隆过滤器在空间和时间方面都有巨大的优势。布隆过滤器存储空间和插入 / 查询时间都是常数。另外 , 散列函数相互之间没有关系,方便由硬件并行实现。布隆过滤器不需要存储元素本身,在某些对保密要求非常严格的场合有优势。

缺点:有一定的误识别率和删除困难。

在 HBase 中使用:用户可以快速判断一个文件是否包含特定的行健。如果 Bloon 过滤器检测文件后,答复说不包含,则肯定不包含;如果包含 Bloom 过滤器答复说包含,则有可能有错,文件可能包含也可能不包含,默认是 1% 的误判率,因此可能有 1% 的多余文件块被加载。这样减少不必要的块加载量,减少 IO ,提升整个集群的吞吐率。

一般使用行级 Bloom 过滤器,行级不行才使用行加列级。

使用布隆过滤器的前提之一是,同一行数据更新集中在少数存储文件上,要不然通过布隆过滤器也无法排除文件,还是得加载这些文件中的特定块。单元格比较小才合适加布隆过滤器,否则,布隆过滤器占用的空间会很大,反而增加 IO 负担。使用行加列布隆过滤器的的情况是:更新的一行数据分布在大部分存储文件,每个存储文件包含该行的一部分,且更新小部分列,且读模式为按列读。综上,决定是否使用布隆过滤器,取决于数据表的读写模式和单元格大小,而过滤原则是能有效过滤掉更多的存储文件。

8版本管理

数据的版本或时间戳分隐式上版本管理和显式版本管理。隐式版本会有一些问题存在,主要发生在集群机器时间不同步时。如客户端写入一行数据, region 服务器时间慢 1 小时,假如客户端再读出最近一个小时的数据,则会把刚写入的数据遗漏。另外, region 拆分时把 region 一分为二,假如一个子 region 被分配到另外一台机器上,当另外这台机器更新数据时,可能时间戳小于之前的时间戳,从而导致最近更新的数据被认为是老数据。自定义版本控制是用户指定自己时间戳的值,创建 自定义的版本控制计划。

  • 发表于:
  • 原文链接https://kuaibao.qq.com/s/20200201A00B6C00?refer=cp_1026
  • 腾讯「腾讯云开发者社区」是腾讯内容开放平台帐号(企鹅号)传播渠道之一,根据《腾讯内容开放平台服务协议》转载发布内容。
  • 如有侵权,请联系 cloudcommunity@tencent.com 删除。

扫码

添加站长 进交流群

领取专属 10元无门槛券

私享最新 技术干货

扫码加入开发者社群
领券