Hbase版本:
hbase shell
version
0.94.15-cdh4.6.0, rUnknown, Wed Feb 26 02:39:52 PST 201
首先,应该明确,在hbase中,索引是存在的,而且有且仅有一个,那就是rowkey。
rowkey的重要性,不言而喻,而且,刚刚接触hbase这个东西时,一定要注意。
唯一
必须在设计上保证其唯一性。
长度
Rowkey是一个二进制码流,Rowkey的长度被很多开发者建议说设计在10~100个字节,64位系统,内存8字节对齐。控制在16个字节,8字节的整数倍利用操作系统的最佳特性,不要超过16个字节。数据的持久化文件HFile中是按照KeyValue存储的。
散列
如果Rowkey是按时间戳的方式递增,建议将Rowkey的高位作为散列字段,由程序循环生成,低位放时间字段,避免所有新数据都在一个 RegionServer上堆积的热点现象。
我的方案(一个)是:
用户ID+事件戳(后缀)+redis自增序列
当然,Hbase也有自己的自增序列:如下表
创建表topic:create 'topic',{NAME=>'cf'}
自增序执行语句:incr 'topic',1008,'cf:incr',1
但是,可惜,通过thrift访问,不能有效的执行并获取,不知道为毛?郁闷中,有知道的,可以告诉我,先谢谢!
其它的,提升HBASE性能的几个地方,如下:
1、使用bloomfilter和mapfile_index_interval
默认情况下创建的table是不打开bloomfilter的(可通过describe table来确认,如看到BLOOMFILTER => ‘NONE’则表示未打开),对于随机读而言这个影响还是比较明显的,由于bloomfilter无法在之后动态打开,因此创建表时最好就处理好,方法类似如此:create ‘t1′, { NAME => ‘f1′, BLOOMFILTER => ‘ROWCOL’ } 或者 create ‘t1′, { NAME => ‘f1′, BLOOMFILTER => ‘ROW’ }
ROWCOL一定比ROW效果好么?不一定的。
ROWCOL只对指定列(Qualifier)的随机读(Get)有效,如果应用中的随机读get,只含row,而没有指定读哪个qualifier,那么设置ROWCOL是没有效果的,这种场景就应该使用ROW;
如果随机读中指定的列(Qualifier)的数目大于等于2,在0.90版本中ROWCOL是无效的,而在0.92版本以后,HBASE-2794对这一情景作了优化,是有效的(通过KeyValueScanner#seekExactly);
如果同一row多个列的数据在应用上是同一时间put的,那么ROW与ROWCOL的效果近似相同,而ROWCOL只对指定了列的随机读才会有效,所以设置为ROW更佳。
另外,适当的减少mapfile_index_interval也可以提升性能,具体参数需要测试。
2、在硬件允许的情况下配足够多的内存给Hbase。
通过修改hbase-env.sh中的
export HBASE_HEAPSIZE=5000 #这里默认为1000m
3、修改java虚拟机属性
在环境允许的情况下换64位的虚拟机
替换掉默认的垃圾回收器,默认的垃圾回收器在多线程环境下会有更多的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、记住HBase是基于列模式的存储,如果一个列族能搞定就不要把它分开成两个。以避免不必要的存储浪费。
6、 Compact,Split的控制
在HBase中,数据在更新时首先写入WAL 日志(HLog)和内存(MemStore)中,MemStore中的数据是排序的,当MemStore累计到一定阈值时,就会创建一个新的MemStore,并且将老的MemStore添加到flush队列,由单独的线程flush到磁盘上,成为一个StoreFile。于此同时, 系统会在zookeeper中记录一个redo point,表示这个时刻之前的变更已经持久化了(minor compact)。
StoreFile是只读的,一旦创建后就不可以再修改。因此Hbase的更新其实是不断追加的操作。当一个Store中的StoreFile达到一定的阈值后,就会进行一次合并(major compact),将对同一个key的修改合并到一起,形成一个大的StoreFile,当StoreFile的大小达到一定阈值后,又会对 StoreFile进行分割(split),等分为两个StoreFile。
由于对表的更新是不断追加的,处理读请求时,需要访问Store中全部的StoreFile和MemStore,将它们按照row key进行合并,由于StoreFile和MemStore都是经过排序的,并且StoreFile带有内存中索引,通常合并过程还是比较快的。
实际应用中,可以考虑必要时手动进行major compact,将同一个row key的修改进行合并形成一个大的StoreFile。同时,可以将StoreFile设置大些,减少split的发生。
7、如果数据量没有达到TB级别或者记录没有上亿,不易发挥出HBase的优势,某些情况下尚不如关系数据库(mycat+mysql 也是不错的搭配)。