文档章节

HBase Compaction算法之ExploringCompactionPolicy

heeee
 heeee
发布于 2015/01/03 18:35
字数 1221
阅读 792
收藏 9

 在0.98版本中,默认的compaction算法换成了ExploringCompactionPolicy,之前是RatioBasedCompactionPolicy

ExploringCompactionPolicy继承RatioBasedCompactionPolicy,重写了applyCompactionPolicy方法,applyCompactionPolicy是对minor compaction的选择文件的策略算法。

applyCompactionPolicy方法内容:

public List<StoreFile> applyCompactionPolicy(final List<StoreFile> candidates,
       boolean mightBeStuck, boolean mayUseOffPeak, int minFiles, int maxFiles) {
    //此ratio为后面算法使用,可设置非高峰时间段的ratio(默认:5.0)从而合并更多的数据
    final double currentRatio = mayUseOffPeak
        ? comConf.getCompactionRatioOffPeak() : comConf.getCompactionRatio();

    // Start off choosing nothing.
    List<StoreFile> bestSelection = new ArrayList<StoreFile>(0);
    List<StoreFile> smallest = mightBeStuck ? new ArrayList<StoreFile>(0) : null;
    long bestSize = 0;
    long smallestSize = Long.MAX_VALUE;

    int opts = 0, optsInRatio = 0, bestStart = -1; // for debug logging
    // Consider every starting place.
    for (int start = 0; start < candidates.size(); start++) {
      // Consider every different sub list permutation in between start and end with min files.
      for (int currentEnd = start + minFiles - 1;
          currentEnd < candidates.size(); currentEnd++) {
        List<StoreFile> potentialMatchFiles = candidates.subList(start, currentEnd + 1);

        // Sanity checks
        if (potentialMatchFiles.size() < minFiles) {
          continue;
        }
        if (potentialMatchFiles.size() > maxFiles) {
          continue;
        }

        // Compute the total size of files that will
        // have to be read if this set of files is compacted.
        long size = getTotalStoreSize(potentialMatchFiles);

        // Store the smallest set of files.  This stored set of files will be used
        // if it looks like the algorithm is stuck.
        if (mightBeStuck && size < smallestSize) {
          smallest = potentialMatchFiles;
          smallestSize = size;
        }

        if (size > comConf.getMaxCompactSize()) {
          continue;
        }

        ++opts;
        if (size >= comConf.getMinCompactSize()
            && !filesInRatio(potentialMatchFiles, currentRatio)) {
          continue;
        }

        ++optsInRatio;
        if (isBetterSelection(bestSelection, bestSize, potentialMatchFiles, size, mightBeStuck)) {
          bestSelection = potentialMatchFiles;
          bestSize = size;
          bestStart = start;
        }
      }
    }
    if (bestSelection.size() == 0 && mightBeStuck) {
      LOG.debug("Exploring compaction algorithm has selected " + smallest.size()
          + " files of size "+ smallestSize + " because the store might be stuck");
      return new ArrayList<StoreFile>(smallest);
    }
    LOG.debug("Exploring compaction algorithm has selected " + bestSelection.size()
        + " files of size " + bestSize + " starting at candidate #" + bestStart +
        " after considering " + opts + " permutations with " + optsInRatio + " in ratio");
    return new ArrayList<StoreFile>(bestSelection);

从代码得知,主要算法如下:

  1. 从头到尾遍历文件,判断所有符合条件的组合
  2. 选择组合的文件数必须 >= minFiles(默认值:3)
  3. 选择组合的文件数必须 <= maxFiles(默认值:10)
  4. 计算组合的文件总大小size,size必须 <= maxCompactSize(通过hbase.hstore.compaction.max.size配置,默认值:LONG.MAX_VALUE,相当于没起作用,官方文档里面说只有觉得compaction经常发生并且没有多大的用时,可以修改这个值)
  5. 组合的文件大小 < minCompactSize 则是符合要求,如果  >= minCompactSize ,还需要判断filesInRatio
  6. filesInRatio算法:FileSize(i) <= ( Sum(0,N,FileSize(_)) - FileSize(i) ) * Ratio,也就是说组合里面的所有单个文件大小都必须满足 singleFileSize <= (totalFileSize - singleFileSize) * currentRatio,此算法的意义是为了限制太大的compaction,选择出来的文件不至于有一个很大的,应该尽可能先合并一些小的大小相差不大的文件,代码如下
    private boolean filesInRatio(final List<StoreFile> files, final double currentRatio) {
        if (files.size() < 2) {
          return true;
        }
    
        long totalFileSize = getTotalStoreSize(files);
    
        for (StoreFile file : files) {
          long singleFileSize = file.getReader().length();
          long sumAllOtherFileSizes = totalFileSize - singleFileSize;
    
          if (singleFileSize > sumAllOtherFileSizes * currentRatio) {
            return false;
          }
        }
        return true;
      }
  7. 寻找最有解,优先选择文件组合文件数多的,当文件数一样多时选择文件数小的,此目的是为了尽可能合并更多的文件并且产生的IO越少越好
    private boolean isBetterSelection(List<StoreFile> bestSelection,
          long bestSize, List<StoreFile> selection, long size, boolean mightBeStuck) {
        if (mightBeStuck && bestSize > 0 && size > 0) {
          // Keep the selection that removes most files for least size. That penaltizes adding
          // large files to compaction, but not small files, so we don't become totally inefficient
          // (might want to tweak that in future). Also, given the current order of looking at
          // permutations, prefer earlier files and smaller selection if the difference is small.
          final double REPLACE_IF_BETTER_BY = 1.05;
          double thresholdQuality = ((double)bestSelection.size() / bestSize) * REPLACE_IF_BETTER_BY;
          return thresholdQuality < ((double)selection.size() / size);
        }
        // Keep if this gets rid of more files.  Or the same number of files for less io.
        return selection.size() > bestSelection.size()
          || (selection.size() == bestSelection.size() && size < bestSize);
      }

主要算法至此结束,下面说说其他细节及其优化部分:

步骤6的ratio默认值是1.2,但是打开了非高峰时间段的优化时,可以有不同的值,非高峰的ratio默认值是5.0,此优化目的是为了在业务低估时可以合并更多的数据,目前此优化只能是天的小说时间段,还不算灵活。

算法中关于mightBeStuck的逻辑部分,这个参数是用来表示是否有可能compaction会被卡住,它的状态是 待选文件数 - 正在做compaction的文件数 + futureFiles(默认值是0,有正在做compaction的文件时是1) >= hbase.hstore.blockingStoreFiles (默认是10,此配置在flush中也会用到,以后分析flush的时候会补充),如果是true时:

  1. 选择文件算法还会去寻找一个最小解。在上文步骤4之前,会记录一个文件大小最小的组合
  2. isBetterSelection部分,算法改为 (bestSelection.size() / bestSize) * 1.05 < selection.size() / size,通过文件大小和文件数的比值去选择一个合适的解
  3. 返回结果时,没有合适的最优解或返回一个最小解。

mightBeStuck的优化部分,相当于保证在很多的文件数的情况下,也可以选出一个最小解去做compaction,而不用再让文件继续增长下去直到有一个合适的组合出现。

此算法跟RatioBasedCompactionPolicy的区别,简单的说就是RatioBasedCompactionPolicy是简单的从头到尾遍历StoreFile列表,遇到一个符合Ratio条件的序列就选定执行Compaction。而ExploringCompactionPolicy则是从头到尾遍历的同时记录下当前最优,然后从中选择一个全局最优列表。

© 著作权归作者所有

共有 人打赏支持
heeee
粉丝 9
博文 22
码字总数 4743
作品 0
深圳
高级程序员
加载中

评论(3)

3696886a
3696886a

引用来自“alexxiyang”的评论

吊炸天,直接解读源代码最靠谱,比人云亦云的二手烟好。可惜现在才关注到
大神,你们还招人吗
3696886a
3696886a

引用来自“alexxiyang”的评论

吊炸天,直接解读源代码最靠谱,比人云亦云的二手烟好。可惜现在才关注到
alexxiyang
alexxiyang
吊炸天,直接解读源代码最靠谱,比人云亦云的二手烟好。可惜现在才关注到
HBase原理之HBase MetaStore&Compaction剖析

1.概述 客户端读写数据是先从HBase Clienr获取RegionServer的元数据信息,比如Region地址信息。在执行数据写操作时,HBase会先写MetaStore,为什么会写到MetaStore。本篇文章将为读者剖析HBa...

HBase技术社区
09/23
0
0
期待已久的Apache HBase2.0正式发布

激动 期待已久的HBase 2.0发布啦! 膜拜 拜读stack大神announce email原文,激动人心的时刻: 邮件简述了HBase 2.0.0 有新版Assignment Manager V2,offhead read/write, in-memory compactio...

tins.wzy
05/02
0
0
中国HBase技术社区第二届MeetUp -笔记摘要

kylin:通过预计算(已知要查询的维度),通过spark,mr遍历计算这些指标,然后将结果存储到hbase中,最后直接查询hbase表即可。 hbase rowkey定义不宜过长,否则存储压力会很大。这里通过使...

bymain
07/21
0
0
HBase最佳实践之HBase查询优化

1.概述 HBase是一个实时的非关系型数据库,用来存储海量数据。但是,在实际使用场景中,在使用HBase API查询HBase中的数据时,有时会发现数据查询会很慢。本篇博客将从客户端优化和服务端优化...

刺猬一号
08/06
0
0
云HBase小组成功抢救某公司自建HBase集群,挽救30+T数据

摘要: 使用过开源HBase的人都知道,运维HBase是多么复杂的事情,集群大的时候,读写压力大,配置稍微不合理一点,就可能会出现集群状态不一致的情况,糟糕一点的直接导致入库、查询某个业务...

阿里云云栖社区
04/18
0
0

没有更多内容

加载失败,请刷新页面

加载更多

并发编程—Java多线程总结

目录 先了解几个概念 多线程:进程和线程是一对多的关系,一个进程(一个程序),由不同的线程来运行。有共享的空间也有独立的空间。 并行: 同时进行,拿两个cpu来跑同样的程序同样的代码片段...

Java干货分享
6分钟前
0
0
Windows Update真的需要向Linux学习

| 虽然简单地将驱动程序从典型的Windows更新中分离出来可能是一种防止这种情况发生的方法,但是Linux甚至更进一步,让用户能够更好地控制他们可以安装的驱动程序。像Ubuntu和Linux Mint这样的...

Linux就该这么学
7分钟前
0
0
Linux学习-0926

4.5/4.6 磁盘格式化 4.7/4.8 磁盘挂载 4.9 手动增加swap分区 一、磁盘格式化 磁盘进行分区后如果不进行格式化,是无法使用的。 linux系统的文件类型: 可以使用使用以下方式进行查看linux系统...

wxy丶
8分钟前
0
0
elasticsearch安装

elasticsearch安装 一、下载: wget https://artifacts.elastic.co/downloads/elasticsearch/elasticsearch-5.6.1.tar.gz 二、解压: tar zxvf elasticsearch-5.6.1.tar.gz 三、改名: ......

小杰java
9分钟前
0
0
Vue router传参 四

传递的方法 //传递<router-link :to="{path:'',query:{id:123}}">产品</router-link>//获取this.$route.query.id 这里可以传params 相当于POST 但 :to里面只能是name query 相当......

大灰狼wow
20分钟前
0
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部