HBase的Compaction理解

时间:2024-03-15 07:33:55

   本文是对自己了解到的HBase Compaction机制做个总结。

 

为什么需要Compaction:

    因为HBase使用了LSM树,将写数据和索引时的随机写转变成了顺序写磁盘,提高了写入时的性能。但是小文件过多的话,查询数据时的I/O次数会增加,影响查询性能。所以HBase提供了Compaction机制,将小文件合并成大文件,目的是查询性能

 

Minor and Major Compaction:

    HBase的Compaction机制分成Minor Compaction和Major Compaction两种。前者只是合并部分HFile文件(老文件在前,新文件在后,此外BulkLoad进来的文件总是排在hbase内部生成的文件之前。同时文件也是按照seqId排序的,因为越是连续数据重复的可能性也就越高),后者是将Region下的所有HFile文件合并成一个大文件,会非常影响性能。所以再生产环境一般会将前者设置成0,表示关闭Major Compaction,再业务低峰期手动触发或者干脆补触发。

HBase的Compaction理解

    Minor Compaction时会删除选取HFile中的TTL过期数据。Major Compaction会清理三类数据:被删除的数据(打了Delete标记的数据)、TTL过期数据、版本号超过设定版本号的数据

 

Compaction触发条件:

    HBase触发Compaction的条件有三种:memstore flush、后台线程周期性检查、手动触发

 

Compaction线程池选择:

    HBase CompacSplitThread类内部对于Split、Compaction等操作专门维护了各自所使用的线程池,和Compaction相关的是如下的longCompactions和shortCompactions...不清楚为什么Compaction要专门分成两个,前者用来处理大规模compaction,后者处理小规模compaction,线程池大小都默认为 1 即只分别提供了一个线程用于相应的compaction,网上看到的说法是建议将其调整到2~5之间。

HBase的Compaction理解

    并不是Major Compaction就一定会交给longCompactions线程池处理。关于HBase compaction分配给longCompactions还是shortCompactions线程池受参数hbase.regionserver.thread.compaction.throttle控制,默认值为2 *maxFlilesToCompact* hbase.hregion.memstore.flush.size。maxFilesToCompact = conf.getInt(HBASE_HSTORE_COMPACTION_MAX_KEY, 10);

    如果flush size 大小是128M,该参数默认值就是2 * 10 * 128M = 2.5G。一次Compaction的文件总大小如果超过该配置,就会分配给longCompactions处理,否则分配给shortCompactions处理。

HBase的Compaction理解

 

Compaction策略:

    HBase Compaction的策略一共有如下四种,HBase 0.96.x版本之前,默认的压缩策略是RatioBasedCompactionPolicy,新版本中默认为ExploringCompactionPolicy

HBase的Compaction理解

    FIFO策略只做这么一件事情,收集所有过期的数据文件并删除,并没有真正执行重写(几个小文件合并成大文件)。因此,对应业务的列族必须设置TTL,否则肯定不适合该策略。应用方式适合时序数据...

    Stripe策略是将一个大Region切分成很多个小sub-region。适用于Region大小小于2G的场景,并且要求Rowkey具有一定的统一格式。使用这种策略可以规避掉Major Compaction,因为Region比较小...

 

ExploringCompactionPolicy详细介绍:

    选择待合并文件走的是RatioBasedCompactionPolicy中的selectCompaction()方法,套用网上一张经典的图:

HBase的Compaction理解

    从旧到新遍历文件,并且BulkLoad的文件在最前面。从文件数量和文件大小两个维度上选择要合并的文件

        1. minFiles(默认值:3) <=  文件数量  <=  maxFiles(默认值:10)

        2. 文件大小 <= maxCompactSize(默认值:LONG.MAX_VALUE)

        3. 同时文件大小 < minCompactSize 则是符合要求,如果  >= minCompactSize ,还需要判断filesInRatio

        FileSize(i) <= ( Sum(0,N,FileSize(_)) - FileSize(i) ) * Ratio

       也就是说组合里面的所有单个文件大小都必须满足 singleFileSize <= (totalFileSize - singleFileSize) * currentRatio,此算法的意义是为了限制太大的compaction,选择出来的文件不至于有一个很大的,应该尽可能先合并一些小的大小相差不大的文件

 

    ExploringCompactionPolicy算法跟RatioBasedCompactionPolicy的区别,在于它还有一个多次遍历选取最优解的操作:

HBase的Compaction理解

    符合条件的合并文件的数量越多越好,数量一样的情况下,优先合并大小比较小的那些

HBase的Compaction理解

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

 

 

Compaction以及Flush时的限速:

    为了防止Compaction以及Flush对业务产生影响,hbase内部会对Compaction和Flush的磁盘I/O写入速度进行限制。限制的方法是sleep让出时间片。因为Flush和Compaction是正相关,Flush越快,需要Compaction的小文件也就越多,而两者都是非常消耗I/O的。

    限速通过一个[0,1.0]之间的一个比例因子来确定,如果超过1,说明此时不应该限速,否则则需要限速。

HBase的Compaction理解

 

 

 

 

 

 

 

参考:

    https://blog.csdn.net/u011598442/article/details/90632702

    https://blog.csdn.net/zyc88888/article/details/79666846

    https://my.oschina.net/u/220934/blog/363270