微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

小记--------hbase数据库预分区设计,rowkey设计及参数调优

  1. 表的设计

1.1预分区设计

一个region维护者startrowkey与endrowkey,如果假如的数据符合某个region维护的rowkey范围,则该数据交给这个region维护,所以我们可以将数据所有投放的分区提前大致的规划好,以提高hbase性能

 

可以通过hbase shell 命令进行创建

create 't9' , 'MM' , SPLITS => ['30000' , '60000' , '90000' ]

create 't4' , { NAME => 'MM' , COMPRESSION => 'snappy' } , {NUMREGIONS => 5 , SPLITALGO => 'HexStringSplit'}

通过javaapi创建

调用HBASEAdmin类的createTable方法进行创建

 

1.2 rowkey设计

首先需要考虑应用场景的读写比列:重写轻读,重读轻写,读写一样

因为数据负载均衡和高效的读取时常是矛盾的

1.在重写轻读的大数据场景中:rowkey的设计应在满足基本查询需求的前提下,更注重整体的吞吐量

2.在重读轻写的大数据场景中:rowkey的设计则应更侧重于如何高效的读取;

 

rowkey字段的选取

唯一性:rowkey必须能够保证唯一的识别一行数据;不论应用什么样的负载均衡场景,rowkey字段应该参考最高频的查询场景

长度原则:rowkey的字段应控制在16个字节之内(在大多数的场景中),从而避免因rowkey字段太长影响Hfile的存储效率

 

A.避免热点的方法1 -reversing (反转)

如果rowkey 本身分布均匀,但是rowkey的尾部数据缺是比较好的随机性,此时,可以考虑将rowkey的信息反转,或者直接将尾部的数据提到rowkey的前部1001 1002 5个

 缺点:场景利于查询中的get但是不利于scan,因为数据在原rowkey上的自然顺序已经被打乱

 

B.避免热点的方法2: - Salting (前部添加随机数)

 Salting的原理实在原rowkey的前面添加固定长度的随机bytes,随机bytes可以保证数据在所有的region上是负载均衡的

 缺点:因为是随机的bytes ,所以原rowkey查询时无法获知随机bytes信息,所以在读取过程中需要倒各个可能的region中查询。所以Salting对于读取是不利的

 

C.避免数据热点的方法3 - Hashing

 基于rowkey的全部或部分数据进行hash,而后将hashing后的值完整替代原rowkey或者替换rowkey的前缀部分

 缺点:与resersing类似,hashing也不利于scan,因为也打乱了原rowkey的自然顺序

 

例:

rowkey与startkey 的关系:

    如果startkey的值为1000 , 2000 , 3000

那么实际的region为:

一个region 0-1000

第二个region 1000-2000

第三个region 2000-3000

第四个region 3000-无穷大

 

rowkey的设计为 随机数(1001)+id+create_time

那么这个rowkey将会落到第二个region上。 原理:会根据region的位数 去到rowkey上从左开始截取相同位数的值做比较,在哪个region的范围就落到哪个region上。

 

1.3列族设计

建议不超过2-3个列簇,因为当某个列簇在flush的时候,它邻近的列簇也会因关联效应被处罚flush,最终导致系统产生更多的IO

建议:将所有相关性很强的key-value都放在同一个列簇下,这样既能做到查询效率最高,也能保持尽可能少的访问不同的磁盘文件

 

1.4 Max Version 最大版本数

可以通过参数HColumnDescriptor.setMaxVersions(int maxVersions)

设置表中数据的最大版本。

如果应用场景只需要保存最新的数据那么可以设置为

HColumnDescriptor.setMaxVersions(1)

 

  1. 一些参数调优

2.1 hbase.client.write.buffer  Hbase客户端写入缓冲区大小

2.2 hbase.regionserver.handler.count  Regionserver中启动RPC服务器实例数量;该参数调小点,适用于单次请求内存消耗较高的Big PUT场景;调大点,适用于单次请求内存消耗低,远程过程调用要求高的场景。需要配合 hbase.client.write.buffer参数进行调优。

估计服务器已使用内存的数量,请用值“hbase.client.write.buffer” *“hbase.regionserver.handler.count”。

 

2.3 hbase.hregion.max.filesize: HStorefile最大值,超过该值则进行切分region

 

2.4 hbase.regionserver.global.memstore.upperLimit:regionserver中所有region的所有memstore总占堆内存比(认为0.4)高水位线,也就是说当regionserver下的memstore的总和等于这个占比的时候进行flush操作

2.5 hbase.regionserver.global.memstore.size.lower.limit:regionserver中所有region的所有memstore总占堆内存比(认为0.95)低水位线,也就是说在进行flush操作时regionserver下的memstore的总和等于0.4*0.95=0.38;

(long) (this.globalMemStoreLimit * this.globalMemStoreLimitLowMarkPercent);

2.6 hfile.block.cache.size;HFile使用的缓存占分配的堆内存占比(认值为0.2);当然是越大越好,如果写比读少很多,开到0.4-0.5也没问题。如果读写较均衡,0.3左右。如果写比读多,就认值即可

 

2.7 hbase.hstore.blockingStoreFiles;store阻塞存储文件

hbase.hstore.blockingWaitTime;store阻塞等待时间;

当store中有超过blockingstorefiles的数量时,会阻塞对HRegion的更新,直到完成storefile的合并或者超过blockingWaitTime的值;所以理论上为了减少写请求的阻塞从而影响regionserver的响应时间,可以将blockingstorefiles值设置无限大。

 

2.8 hbase.hregion.memstore.block.multiplier;hbase memstore块乘法器;

一个region里的memstore占用内存大小超过hbase.hregion.memstore.flush.size两倍的大小时,block该region的所有请求,进行flush,释放内存。虽然我们设置了region所占用的memstores总内存大小,比如64M,但想象一下,在最后63.9M的时候,我Put了一个200M的数据,此时memstore的大小会瞬间暴涨到超过预期的hbase.hregion.memstore.flush.size的几倍。这个参数的作用是当memstore的大小增至超过hbase.hregion.memstore.flush.size 2倍时,block所有请求,遏制风险进一步扩大;

所以需要预估应用场景中会不会出现突发写请求暴涨,如果有可以调大这个参数值

 

2.9 hbase.hregion.memstore.flush.size;单个region的memstore的值达到该值时会自动触发flush操作(认值为128M)

 

  1. 分别调整Master和regionserver的java堆栈大小(heapsize)

由于认的regionserver的内存才1G,而memstore认是占40%,所以分配给memstore的才400M,在实际生产环境下很容易阻塞,可以通过HBASE_HEAPSIZE参数分别调整Master和RegionServer的内存

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐