HBase性能优化方法总结(一):表的设计

本文主要是从HBase应用程序设计与开发的角度,总结几种经常使用的性能优化方法。有关HBase系统配置级别的优化,可参考:淘宝Ken Wu同窗的博客html

下面是本文总结的第一部份内容:表的设计相关的优化方法。apache

1. 表的设计

1.1 Pre-Creating Regions

默认状况下,在建立HBase表的时候会自动建立一个region分区,当导入数据的时候,全部的HBase客户端都向这一个region写数据, 直到这个region足够大了才进行切分。一种能够加快批量写入速度的方法是经过预先建立一些空的regions,这样当数据写入HBase时,会按照 region分区状况,在集群内作数据的负载均衡。数组

有关预分区,详情参见:Table Creation: Pre-Creating Regions,下面是一个例子:缓存

复制代码

   createTable(HBaseAdmin admin, HTableDescriptor table, [][] splits)
 IOException {
   {
    admin.createTable(table, splits);
     ;
  }  (TableExistsException e) {
    logger.info("table " + table.getNameAsString() + " already exists");
         ;  
  }
}

  [][] getHexSplits(String startKey, String endKey,  numRegions) {
  [][] splits =  [numRegions-1][];
  BigInteger lowestKey =  BigInteger(startKey, 16);
  BigInteger highestKey =  BigInteger(endKey, 16);
  BigInteger range = highestKey.subtract(lowestKey);
  BigInteger regionIncrement = range.divide(BigInteger.valueOf(numRegions));
  lowestKey = lowestKey.add(regionIncrement);
  ( i=0; i < numRegions-1;i++) {
    BigInteger key = lowestKey.add(regionIncrement.multiply(BigInteger.valueOf(i)));
    [] b = String.format("%016x", key).getBytes();
    splits[i] = b;
  }
   splits;
}

复制代码

1.2 Row Key

HBase中row key用来检索表中的记录,支持如下三种方式:性能优化

  • 经过单个row key访问:即按照某个row key键值进行get操做;负载均衡

  • 经过row key的range进行scan:即经过设置startRowKey和endRowKey,在这个范围内进行扫描;ide

  • 全表扫描:即直接扫描整张表中全部行记录。性能

在HBase中,row key能够是任意字符串,最大长度64KB,实际应用中通常为10~100bytes,存为byte[]字节数组,通常设计成定长的测试

row key是按照字典序存储,所以,设计row key时,要充分利用这个排序特色,将常常一块儿读取的数据存储到一块,将最近可能会被访问的数据放在一块。优化

举个例子:若是最近写入HBase表中的数据是最可能被访问的,能够考虑将时间戳做为row key的一部分,因为是字典序排序,因此可使用Long.MAX_VALUE - timestamp做为row key,这样能保证新写入的数据在读取时能够被快速命中。

1.3 Column Family

不要在一张表里定义太多的column family。目前Hbase并不 能很好的处理超过2~3个column family的表。由于某个column family在flush的时候,它邻近的column family也会因关联效应被触发flush,最终致使系统产生更多的I/O。感兴趣的同窗能够对本身的HBase集群进行实际测试,从获得的测试结果数 据验证一下。

1.4 In Memory

建立表的时候,能够经过HColumnDescriptor.setInMemory(true)将表放到RegionServer的缓存中,保证在读取的时候被cache命中。

1.5 Max Version

建立表的时候,能够经过HColumnDescriptor.setMaxVersions(int maxVersions)设置表中数据的最大版本,若是只须要保存最新版本的数据,那么能够设置setMaxVersions(1)。

1.6 Time To Live

建立表的时候,能够经过HColumnDescriptor.setTimeToLive(int timeToLive)设置表中数据的存储生命期,过时数据将自动被删除,例如若是只须要存储最近两天的数据,那么能够设置 setTimeToLive(2 * 24 * 60 * 60)。

1.7 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的发生。

相关文章
相关标签/搜索