zoukankan      html  css  js  c++  java
  • HBase性能优化方法总结(一):表的设计

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

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

    1. 表的设计

    1.1 Pre-Creating Regions

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

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

    复制代码
    public static boolean createTable(HBaseAdmin admin, HTableDescriptor table, byte[][] splits)
    throws IOException {
    try {
    admin.createTable(table, splits);
    return true;
    } catch (TableExistsException e) {
    logger.info("table " + table.getNameAsString() + " already exists");
    // the table already exists...
    return false;
    }
    }

    public static byte[][] getHexSplits(String startKey, String endKey, int numRegions) {
    byte[][] splits = new byte[numRegions-1][];
    BigInteger lowestKey = new BigInteger(startKey, 16);
    BigInteger highestKey = new BigInteger(endKey, 16);
    BigInteger range = highestKey.subtract(lowestKey);
    BigInteger regionIncrement = range.divide(BigInteger.valueOf(numRegions));
    lowestKey = lowestKey.add(regionIncrement);
    for(int i=0; i < numRegions-1;i++) {
    BigInteger key = lowestKey.add(regionIncrement.multiply(BigInteger.valueOf(i)));
    byte[] b = String.format("%016x", key).getBytes();
    splits[i] = b;
    }
    return splits;
    }
    复制代码

    1.2 Row Key

    HBase中row key用来检索表中的记录,支持以下三种方式:

    • 通过单个row key访问:即按照某个row key键值进行get操作;
    • 通过row key的range进行scan:即通过设置startRowKey和endRowKey,在这个范围内进行扫描;
    • 全表扫描:即直接扫描整张表中所有行记录。

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

    http://www.cnblogs.com/panfeng412/archive/2012/03/08/hbase-performance-tuning-section1.html

  • 相关阅读:
    UOJ 216 Jakarta Skyscrapers
    JDBC Connection使用
    jmeter 参数化5_Count 计数器
    jmeter 参数化4_Function Helper中的函数
    jmeter 参数化3_User Defined Variables(用户自定义变量)
    jmeter 参数化2_CSV Data Set Config
    jmeter 参数化1_User Parameters(用户参数)
    Jmeter --Json Extractor (后置处理器)
    2、pycharm中设置pytest为默认运行
    1、pip不是内部运行程序 解决方法
  • 原文地址:https://www.cnblogs.com/1130136248wlxk/p/4998966.html
Copyright © 2011-2022 走看看