优化hbase的查询提升读写速率优化案例及性能提升的几种方法

在初期,我们采用的逻辑是:将A表中的数据读取一行,根据其中的某个字段去组织一个GET,然后立刻提交,从B表取得要查询的字段的值,组织成一个PUT,并提交到A表。那么这么做的话,
1.完全发挥不出hbase的效率的原因是什么?


2.使用bloomfilter和mapfile_index_interval如何提升性能?
3.如何设置hbase的内存?
4.如何增大RPC的数量?
扩展:

5.为什么HBase是基于列模式的存储?

image

1.优化案例

环境:suse 8G内存,8核,12T磁盘
hbase master 占一台,其他7台作为hbase的region server
注意:此处不讨论hadoop

情景:
我们有7亿的数据,需要做查询操作,需要从1.7亿的表中查找一个字段,并写入到7亿数据的表中。
这里为了描述方便,将7亿数据的表称为:A表,1.7亿数据的表称为B表。

      在初期,我们采用的逻辑是:将A表中的数据读取一行,根据其中的某个字段去组织一个GET,然后
      立刻提交,从B表取得要查询的字段的值,组织成一个PUT,并提交到A表。
      那么这么做的话,完全发挥不出hbase的效率,因为每个get之间它的key不一定连续,或者说是在同一范围
      而hbase的服务端会根据每个请求去加载数据到内存,由于请求的块分散,那么数据在内存中的替换过多的频繁。
      很有可能和直接读取磁盘数据差不多。
      并且采用这种逻辑去处理数据,需要花费时间太多。差不多是10W行读写数据需要40分钟。这对于A表的更新操作
      完全是不能接受的。

      之后,通过读数据的读取操作进行封装,组织成一个ArrayList<Get> 当到一定程度的时候采取提交。这里还有一个情况就是
      有些数据查询不到,那么需要去连接数据库去申请一个自动分配的值,并立刻提交,因为后面可能有请求这个数据。
      这就需要分开处理。
      在组织GET 列表的时候需要先查询,注意,不要采用table.get去取一个cell的值并判断是否为null来处理。
      而是用table.exist(get) 去查询,这是在server-side跑的,效率要高很多。
      对于查询不到的值立刻申请值并写入A表。
      对于查询的到的,那么就可前面说的组织get 加入到GET列表中,到一定程度再去一次提交,在取到值之后,
      在根据将循环数据的记录,将这些组织成put,数量和GET列表一样,不要去具体指定,在循环一次后直接table.put

      其他参数修改方面,写的都很多,这里就不提了。

处理速度(取至其中一台服务器中跑的任务):
2011-12-30 17:10:03 Start Write Lines:1700000
2011-12-30 17:14:10 Writed Lines:1700000
2011-12-30 17:14:11 Start Write Lines:1800000
2011-12-30 17:18:21 Writed Lines:1800000
2011-12-30 17:18:22 Start Write Lines:1900000
2011-12-30 17:22:29 Writed Lines:1900000
2011-12-30 17:22:29 Start Write Lines:2000000
2011-12-30 17:26:37 Writed Lines:2000000
2011-12-30 17:26:37 Start Write Lines:2100000

大约是查询,写入速度是4分钟处理10W行数据。

也就是4000/s的速率,较之前的处理方式提升了一个量级

image

性能提升方法

1、使用bloomfilter和mapfile_index_interval

|

Bloomfilter(开启/未开启=1/0)

|

mapfile_index_interval

|

Exists(0-10000)/ms

|

Get(10001 - 20000)/ms

|
|

0

|

128

|

22460

|

23715

|
|

0

|

0

|

11897

|

11416

|
|

0

|

64

|

13692

|

14034

|
|

1

|

128

|

3275

|

3686

|
|

1

|

64

|

2961

|

3010

|
|

1

|

0

|

3339

|

3498

|

测试环境为:单机,规模为10万条数据。随机在10000条数据中有99条存在的情况下。

结论:开启bloomfilter比没开启要快3、4倍。而适当的减少mapfile_index_interval可以提升性能

注意:在1.9.3版本的hbase中,bloomfilter是不支持的,存在一个bug,可以通过如下的修改加以改正:
(1)、在方法org.apache.hadoop.hbase.regionserver.HStore.createReaders()中,找到如下行
BloomFilterMapFile.Reader reader = file.getReader(fs, false, false);
将其改成
BloomFilterMapFile.Reader reader = file.getReader(fs, this.family.isBloomfilter(), false);
(2)、在方法org.apache.hadoop.hbase.HColumnDescriptor.toString()中,找到如下的代码行
if (key != null && key.toUpperCase().equals(BLOOMFILTER)) {
// Don't emit bloomfilter. Its not working.
continue;
}
将其注释掉

2、hbase对于内存有特别的嗜好,在硬件允许的情况下配足够多的内存给它。
通过修改hbase-env.sh中的
export HBASE_HEAPSIZE=3000 #这里默认为1000m

3、修改java虚拟机属性
(1)、在环境允许的情况下换64位的虚拟机
(2)、替换掉默认的垃圾回收器,因为默认的垃圾回收器在多线程环境下会有更多的wait等待
export HBASE_OPTS="-server -XX:NewSize=6m -XX:MaxNewSize=6m -XX:+UseConcMarkSweepGC -XX:+CMSIncrementalMode"

4、增大RPC数量
通过修改hbase-site.xml中的
hbase.regionserver.handler.count属性,可以适当的放大。默认值为10有点小

5、做程序开发是注意的地方
(1)、需要判断所求的数据行是否存在时,尽量不要用HTable.exists(final byte [] row) 而用HTable.exists(final byte [] row, final byte[] column)等带列族的方法替代。
(2)、不要使用HTable.get(final byte [] row, final byte [] column) == null来判断所求的数据存在,而是用HTable.exists(final byte [] row, final byte[] column)替代
(3)、HTable.close()方法少用.因为我遇到过一些很令人费解的错误

6、记住HBase是基于列模式的存储,如果一个列族能搞定就不要把它分开成两个,关系数据库的那套在这里很不实用.分成多个列来存储会浪费更多的空间,除非你认为现在的硬盘和白菜一个价。

7、如果数据量没有达到TB级别或者没有上亿条记录,很难发挥HBase的优势,建议换关系数据库或别的存储技术。

推荐资源:HBase性能深度分析和性能调优

上文提到了Bloom Filter,这里补充一下:
Bloom Filter原理及在Hbase上的应用

首先最重要的是要搞清楚Bloom Filter是做什么的,看了几篇文章的表述,其实最根本的就是:

判断一个元素是否属于这个集合。

如果这个集合中的元素足够多,那么通过传统方法进行如上判断耗时会很多,Bloom Filter就是一种利用很少的空间换取时间的非常实用的方法。但是要说明的是:Bloom Filter的这种高效是有一定代价的,在判断一个元素是否属于某个集合时,有可能会把不属于这个集合的元素误认为属于这个集合(false positive)。因此,Bloom Filter不适合那些“零错误”的应用场合。而在能容忍低错误率的应用场合下,Bloom Filter通过极少的错误换取了存储空间的极大节省。

下面描述下Bloom Filter的原理:

Bloom Filter是m位的数组,且这m个数组的每一位都是零。

image

Step 1 映射:假如我们有A={x1,x2,x3….xn} n个元素,那么我们需要k个相互独立的哈希函数,将其中每个元素进行k次哈希,他们分别将这个元素映射到m位的数组中,而其映射的位置就置为1,如果有重复的元素映射到这个数组的同一个元素,那么这个元素只会记录一次1,后续的映射将不会改变的这个元素的值。如图:

image

Step 2 判断:在判断B={y1,y2} 这两个元素是否属于A集合时,我们就将这两个元素分别进行上步映射中的k个哈希函数的哈希,如果结果全为1,那么就判断属于A集合,否则判断其不属于A集合。如下图 y2属于,y1则不属于。

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 219,110评论 6 508
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 93,443评论 3 395
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 165,474评论 0 356
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,881评论 1 295
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,902评论 6 392
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,698评论 1 305
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,418评论 3 419
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,332评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,796评论 1 316
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,968评论 3 337
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 40,110评论 1 351
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,792评论 5 346
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,455评论 3 331
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 32,003评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 33,130评论 1 272
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 48,348评论 3 373
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 45,047评论 2 355

推荐阅读更多精彩内容