HBase选择Store file做compaction的算法

2023-11-07

The algorithm is basically as follows:

Run over the set of all store files, from oldest to youngest

If there are more than 3 (hbase.hstore.compactionThreshold) store files left and the current store file is 20% larger then the sum of all younger store files, and it is larger than the memstore flush size, then we go on to the next, younger, store file and repeat step 2.

Once one of the conditions in step two is not valid anymore, the store files from the current one to the youngest one are the ones that will be merged together. If there are less than the compactionThreshold, no merge will be performed. There is also a limit which prevents more than 10 (hbase.hstore.compaction.max) store files to be merged in one compaction.

与compaction相关的配置参数,可以在Hbase-default.xml或者Hbase-site.xml进行查看或者配置。

this.minFilesToCompact = Math.max(2, conf.getInt(“hbase.hstore.compaction.min”, /old name/ conf.getInt(“hbase.hstore.compactionThreshold”, 3)));this.majorCompactionTime = getNextMajorCompactTime();this.maxFilesToCompact = conf.getInt(“hbase.hstore.compaction.max”, 10);this.minCompactSize = conf.getLong(“hbase.hstore.compaction.min.size”, this.region.memstoreFlushSize);this.maxCompactSize = conf.getLong(“hbase.hstore.compaction.max.size”, Long.MAX_VALUE);

2011/7/11更新选择哪些store files去做min compaction的代码注释:

//
// Compaction
//

/**

  • Compact the StoreFiles. This method may take some time, so the calling

  • thread must be able to block for long periods.

  • During this time, the Store can work as usual, getting values from

  • StoreFiles and writing new StoreFiles from the memstore.

  • Existing StoreFiles are not destroyed until the new compacted StoreFile is

  • completely written-out to disk.

  • The compactLock prevents multiple simultaneous compactions.

  • The structureLock prevents us from interfering with other write operations.

  • We don't want to hold the structureLock for the whole time, as a compact()

  • can be lengthy and we want to allow cache-flushes during this period.

  • @param forceMajor True to force a major compaction regardless of thresholds

  • @return row to split around if a split is needed, null otherwise

  • @throws IOException
    */
    StoreSize compact(final boolean forceMajor) throws IOException {
    boolean forceSplit = this.region.shouldForceSplit();
    boolean majorcompaction = forceMajor;
    synchronized (compactLock) { // 一次只能有一个thread进行compaction, store范围,region范围还是region server范围?
    this.lastCompactSize = 0;

    // filesToCompact are sorted oldest to newest.
    List filesToCompact = this.storefiles;
    if (filesToCompact.isEmpty()) {
    LOG.debug(this.storeNameStr + “: no store files to compact”);
    return null;
    }

    // Check to see if we need to do a major compaction on this region.
    // If so, change doMajorCompaction to true to skip the incremental
    // compacting below. Only check if doMajorCompaction is not true.
    if (!majorcompaction) {
    majorcompaction = isMajorCompaction(filesToCompact);
    }

    boolean references = hasReferences(filesToCompact);
    if (!majorcompaction && !references &&
    (forceSplit || (filesToCompact.size() < compactionThreshold))) {
    return checkSplit(forceSplit);
    }

    /* get store file sizes for incremental compacting selection.

    • normal skew:
    •    older ----> newer
      
    • _
    • | | _
    • | | | | _
    • –|-|- |-|- |-|—-------------- minCompactSize(参数配置)
    • | | | | | | | | _ | |
    • | | | | | | | | | | | |
    • | | | | | | | | | | | |
      /
      int countOfFiles = filesToCompact.size();
      long [] fileSizes = new long[countOfFiles];
      long [] sumSize = new long[countOfFiles];
      for (int i = countOfFiles-1; i >= 0; --i) {
      StoreFile file = filesToCompact.get(i);
      Path path = file.getPath();
      if (path == null) {
      LOG.error("Path is null for " + file);
      return null;
      }
      StoreFile.Reader r = file.getReader();
      if (r == null) {
      LOG.error(“StoreFile " + file + " has a null Reader”);
      return null;
      }
      fileSizes[i] = file.getReader().length();
      // calculate the sum of fileSizes[i,i+maxFilesToCompact-1) for algo
      int tooFar = i + this.maxFilesToCompact - 1;
      /
      *
    • e.g:sum_size保存的是相邻的maxFielsToCompact个storeFile大小的和
    • index : 0, 1, 2, 3 4, 5
    • f size: 10, 20, 15, 25, 15, 10
    • fooFar: 2, 3, 4, 5, 6, 7
    • s size: 45, 60, 55, 50, 25, 10 (maxFilesToCompact = 3, countOfFiles = 6)
      */
      sumSize[i] = fileSizes[i]
      + ((i+1 < countOfFiles) ? sumSize[i+1] : 0)
      - ((tooFar < countOfFiles) ? fileSizes[tooFar] : 0);
      }

    long totalSize = 0;
    if (!majorcompaction && !references) {
    // we’re doing a minor compaction, let’s see what files are applicable
    int start = 0;
    double r = this.compactRatio;

    /* Start at the oldest file and stop when you find the first file that
    * meets compaction criteria:
    * 从老的storefile到新的storefile进行遍历,停止的条件是当遇到一个storefile的
    * 大小小于minCompactSize的时候,或者是小于后面maxFilesToCompact个storefile
    * 大小的和乘以compactRatio(默认1.2)
    *
    * X <= minCompactSize || X <= SUM_ * compactRatio ==> 停止
    * X > minCompactSize && x > SUM_ * compactRation  ==> 继续扫描
    * X > max(minCompactSize, SUM_ * compactRation)  ==> 继续扫描
    *  (1) a recently-flushed, small file (i.e. <= minCompactSize)
    *      OR
    *  (2) within the compactRatio of sum(newer_files)
    * Given normal skew, any newer files will also meet this criteria
    *
    * Additional Note:
    * If fileSizes.size() >> maxFilesToCompact, we will recurse on
    * compact().  Consider the oldest files first to avoid a
    * situation where we always compact [end-threshold,end).  Then, the
    * last file becomes an aggregate of the previous compactions.
    */
    /*
    * 至少有compactionThreshold这么多个store files
    * 至少满足停止条件(1)(2)的时候
    * ==>
    * 才能进行min compaction
    */
    while(countOfFiles - start >= this.compactionThreshold &&
          fileSizes[start] >
            Math.max(minCompactSize, (long)(sumSize[start+1] * r))) {
      ++start;
    }
    
    // 确定我们一次min compaction最多只能有maxFilesToCompact个store file
    int end = Math.min(countOfFiles, start + this.maxFilesToCompact);
    // 包含在这次min compaction里面的store file总大小
    totalSize = fileSizes[start]
              + ((start+1 < countOfFiles) ? sumSize[start+1] : 0);
    
    // if we don't have enough files to compact, just wait
    if (end - start < this.compactionThreshold) {
      if (LOG.isDebugEnabled()) {
        LOG.debug("Skipped compaction of " + this.storeNameStr
          + " because only " + (end - start) + " file(s) of size "
          + StringUtils.humanReadableInt(totalSize)
          + " meet compaction criteria.");
      }
      return checkSplit(forceSplit);
    }
    
    if (0 == start && end == countOfFiles) {
      // we decided all the files were candidates! major compact
      majorcompaction = true;
    } else {
      // 从待compaction的store file list中先切除一批满足条件的store file去做min compaction
      filesToCompact = new ArrayList<StoreFile>(filesToCompact.subList(start,
        end));
    }
    // 进入if的条件是major compaction为false,出来的时候major compaction可能是false,也可能是true
    

    } else {
    // all files included in this compaction
    for (long i : fileSizes) {
    totalSize += i;
    }
    }
    this.lastCompactSize = totalSize;

    // Max-sequenceID is the last key in the files we’re compacting
    long maxId = StoreFile.getMaxSequenceIdInList(filesToCompact);

    // Ready to go. Have list of files to compact.
    LOG.info(“Started compaction of " + filesToCompact.size() + " file(s) in cf=” +
    this.storeNameStr +
    (references? “, hasReferences=true,”: " ") + " into " +
    region.getTmpDir() + “, seqid=” + maxId +
    “, totalSize=” + StringUtils.humanReadableInt(totalSize));
    // 选择好了store file, compact就是真正去做merge的函数了
    StoreFile.Writer writer = compact(filesToCompact, majorcompaction, maxId);
    // Move the compaction into place.
    StoreFile sf = completeCompaction(filesToCompact, writer);
    if (LOG.isInfoEnabled()) {
    LOG.info(“Completed” + (majorcompaction? " major ": " ") +
    “compaction of " + filesToCompact.size() +
    " file(s), new file=” + (sf == null? “none”: sf.toString()) +
    “, size=” + (sf == null? “none”: StringUtils.humanReadableInt(sf.getReader().length())) +
    "; total size for store is " + StringUtils.humanReadableInt(storeSize));
    }
    }
    return checkSplit(forceSplit);
    }

2011.12.13添加

几个关于compaction的hbase jira:

HBASE-3189 Stagger Major Compactions

HBASE-3209 : New Compaction Algorithm

HBASE-1476 Multithreaded Compactions

HBASE-3857 Change the HFile Format

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

HBase选择Store file做compaction的算法 的相关文章

  • 运输例外

    我正在尝试导入 happybase 但在连接时收到以下错误消息 我已经运行了 Hadoop 伪节点集群和 Hbase 安装的组件版本如下 Hadoop 版本 1 0 4 Hbase 版本 0 94 4 快乐基地 0 4 有人可以查看下面的例
  • Hbase 客户端因 /hbase 错误导致连接丢失

    我快要疯了 安装了Hadoop Hbase 一切都在运行 opt jdk1 6 0 24 bin jps 23261 ThriftServer 22582 QuorumPeerMain 21969 NameNode 23500 Jps 23
  • Spark 使用数据局部性吗?

    我正在尝试了解 Apache Spark 的内部结构 我想知道 Spark 是否使用某些机制来确保从 InputFormat 读取或写入 OutputFormat 或 Spark 本机支持的其他格式而不是从 MapReduce 派生的格式
  • 如何通过部分行键过滤HBase的Scan?

    我有带有行键的 HBase 表 其中包含文本 ID 和时间戳 如下所示 string id1 1470913344067 string id1 1470913345067 string id2 1470913344067 string id
  • 将 Jar 文件添加到 WEB-INF/lib [重复]

    这个问题在这里已经有答案了 我是 Eclipse Java 和 Linux 的新手 我搜索这个问题 但没有找到答案 我想编写一个操作 HBase 表的程序 所以我有一些与 HBase 相关的 Jar 文件 在普通的 Java 应用程序中 我
  • HBase:复制是如何工作的?

    我目前正在将 HBase 作为数据存储进行评估 但有一个问题没有得到解答 HBase 在许多节点上存储同一对象的许多副本 也称为复制 由于HBase具有所谓的强一致性 相比之下最终一致 它保证每个副本在读取时返回相同的值 据我了解 HBas
  • HBase区域服务器和Hadoop数据节点应该在同一台机器上吗?

    抱歉 我没有资源来设置集群来测试它 我只是想知道 我可以将 hbase 区域服务器部署在 hadoop 数据节点计算机之外的单独计算机上吗 我想答案是肯定的 但我不确定 hbase区域服务器和hadoop数据节点部署在不同的机器上是好是坏
  • 在 Java 中连接来自 HBase 的两个结果集?

    是否可以连接从 java 中的 hbase 检索的两个或多个结果集 不 不可能加入 JDBC 结果集 但是 您可以获取它们的结果并手动组合它们 如果它们兼容 如果它们属于同一实体 EDIT 如果您只需要组合两个相同类型的列表 您可以这样做
  • 如何更改hbase表中列族的名称

    我有一个 Hbase 表 只有 1 个列族 cf1 下面有 100 列 我需要将 cf1 更改为新的列族 CF1 简而言之 我需要修改列族名称 我已经浏览了以下链接http comments gmane org gmane comp jav
  • 将 protobuf3 与一些依赖于 Java 中的 protobuf2 的库一起使用

    我使用protobuf3来表示我们的数据 虽然我们需要hbase来存储数据 但似乎hbase依赖于protobuf2 当我编写以下行来创建 hbase 表时 admin createTable desc 然后我得到一个例外 NoClassD
  • 如何在spark中配置hbase?

    Spark连接hbase的步骤是什么 我有两者的主地址 我是否只需将 hbase 地址添加到 Spark 类路径中 这篇关于 Spark 与 HBase 连接的文章应该会有所帮助 http www vidyasource com blog
  • Titan-1.0.0+Hbase-0.98.20使用java远程模式连接错误

    我正在学习Titan数据库 我已经在本地模式下成功运行了它 现在 我尝试在 Titan 文档中介绍的 远程服务器模式 下使用 Titan 数据库 我的 Titan 版本是 Titan 1 0 0 hadoop1 我的 LAN 中有集群 包括
  • 如何将多个 QualifierFilter 应用于 HBase 中的一行

    我们想使用两个 QualifierFilters 过滤 HBase 表上的扫描 意味着我们只想获取表中确实具有特定列 col A 的行AND 某个其他列 col B 我们当前的方法如下所示 FilterList filterList new
  • 使用 MultipleOutputs 写入 MapReduce 中的 HBase

    我目前有一个 MapReduce 作业 它使用 MultipleOutputs 将数据发送到多个 HDFS 位置 完成后 我使用 HBase 客户端调用 在 MR 之外 将一些相同的元素添加到一些 HBase 表中 使用 TableOutp
  • 错误:org.apache.hadoop.hbase.MasterNotRunningException:null+hbase+hadoop

    我最近用两台机器 在ubuntu上 配置了hadoop集群 到目前为止效果很好 但是当我尝试在上面的 hadoop 集群上配置 hbase 时 它 显示错误 这就是我所做的 我有两台机器 192 168 1 110 Hadoop主站 192
  • hbase api - 通过行ID列表获取数据行信息

    是否可以通过hbase java API通过行id列表获取hbase数据记录 例如 我有一个已知的 hbase 行 ID 列表 mykey1 myhash1 mykey1 myhash2 mykey1 myhash3 mykey2 myha
  • 如果 HBase 不是运行在分布式环境中,它还有意义吗?

    我正在构建数据索引 这将需要以形式存储大量三元组 document term weight 我将存储多达几百万个这样的行 目前我正在 MySQL 中将其作为一个简单的表来执行 我将文档和术语标识符存储为字符串值 而不是其他表的外键 我正在重
  • 从 Storm Bolt 将行插入 HBase

    我希望能够从分布式 非本地 Storm 拓扑将新条目写入 HBase 有一些 GitHub 项目提供以下任一功能 HBase 映射器 https github com ptgoetz storm hbase or 预制风暴螺栓 https
  • 获取行 HBase 的特定列族中的列

    我正在编写一个应用程序 通过 JSP 显示 HBase 中特定表中的数据 我想获取一行的特定列族中的所有列 有什么办法可以做到这一点吗 public String getColumnsInColumnFamily Result r Stri
  • 使用 Cassandra 进行单元版本控制

    我的应用程序使用 AbstractFactory 作为 DAO 层 因此一旦实现了 HBase DAO 系列 创建 Cassandra DAO 系列并从多个角度查看差异对我来说将是非常好的 不管怎样 试图做到这一点 我看到 Cassandr

随机推荐

  • Docker 学习笔记(九)-- Dockerfile 构建Tomcat 实战测试

    1 准备镜像文件 Tomcat 压缩包 Apache Tomcat Welcome 依赖的 JDK 压缩包 Java Downloads Oracle https www aliyundrive com s YzH6o5G5QUu 下载 后
  • osg环境搭建与使用

    目录 环境安装 案例一 案例二 案例三 案例四 我的vs2022 window11 环境安装 看这个文章即可 博客很详细 按照这个没问题的 5条消息 OSG OSG环境部署 OSG3 6 5 vs2017 win10 x64 超详细 osg
  • 调用EAS单据转换规则(BOTP),生成下游单据

    代码调用单据转换规则 生成下游单据 调用BOTP生成下游单据 用于后台 param ctx 上下文 param sourceType 源单类型 param destType 目标单据类型 param sourceColl 源单集合 para
  • NER问题的模型训练5种相关提升tricks

    NER问题的模型训练5种相关提升tricks 一 cMedQANER数据集介绍 用于医疗领域的命名实体识别任务 实体标签 physiology test disease time drug symptom body department c
  • 快速实现M5311 NBIOT TCP通信

    M5311作为TCP Client和Server通信 一 本例程实现功能 二 Core提供的TCP功能介绍 三 接线图 五 完整代码 前言 虽然在如今的物联网开发中 像MQTT COAP这些专门为了物联网而诞生的协议逐渐成为主流 但其实TC
  • 【VMware】VM虚拟机启动系统黑屏及操作系统未找到 多种详细解决方案

    作者 MiTu 本帖内容著作权归作者所有 转载请务必保留本文链接 VM虚拟机启动黑屏 解决方案大全 前言 1 BIOS虚拟设备支持 2 LSP问题 3 虚拟机配置 4 硬盘启动优先级 5 Opearating System not foun
  • 将sqlite源码放进自己的工程一起编译

    在sqlite官网上http www sqlite com download html下载最新的源代码 目前最新的版本是3 8 11 sqlite的源码包有两类 一类是sqlite amalgamation 3081101 zip 这个包里
  • (三十七)论文阅读

    简介 图1 论文原文 论文聚焦的是在目标检测中的 A n c h o r rm Anchor
  • mysql describe_mysql8 参考手册--EXPLAIN、DESCRIBE语句

    EXPLAIN DESCRIBE DESC tbl name col name wild EXPLAIN DESCRIBE DESC explain type explainable stmt FOR CONNECTION connecti
  • 工控随笔_10_西门子_WinCC的VBS脚本_01_基础入门

    很多人都认为VB语言或者VBS脚本语言是一种很low的语言 从心里看不起VB或者VBS 但是其实VBS不仅可以做为系统管理员的利器 同样在工控领域VBS语言大有用武之地 西门子的WinCC提供了两种脚本语言 C脚本和VBS脚本 通过这两种脚
  • [Unity]改变代码运行场景等待时间太长怎么办

    改变代码运行场景速度太慢怎么办 改变一次代码5分钟 运行场景等待5分钟怎么办 是否是因为项目工程 中的资源文件太大 文件数量太多 尝试把这些资源文件 放入 非 项目工程文件夹Assets内 打包后从服务器下载 这些资源文件 zip文件
  • 网络基础:双绞线

    双绞线的线序 EIA TIA的布线标准中规定了两种双绞线的线序 568A与568B 标准568A 绿白 1 绿 2 橙白 3 蓝 4 蓝白 5 橙 6 褐白 7 褐 8 标准568B 橙白 1 橙 2 绿白 3 蓝 4 蓝白 5 绿 6 褐
  • 用vue构建项目笔记5(在vue-cli项目中引用公用方法)(vue resource统一处理)

    之前用cli脚手架构建的项目废了 又让我改成jq了 悲剧 这次这个项目用纯vue实现了 哈哈 下面介绍如何引入全局方法供每个组件都能调用 1 创建一个js文件 我起的名字叫做 common js 放在assets gt js下 2 在com
  • vue文件夹上传源码

    一 功能性需求与非功能性需求 要求操作便利 一次选择多个文件和文件夹进行上传 支持PC端全平台操作系统 Windows Linux Mac 支持文件和文件夹的批量下载 断点续传 刷新页面后继续传输 关闭浏览器后保留进度信息 支持文件夹批量上
  • [论文解读]UNet++解读 + 它是如何对UNet改进 + 作者的研究态度和方式

    UNet 论文 地址 UNet 论文翻译 地址 UNet 源代码 地址 UNet 作者在知乎 上进行了解读 里面还有视频的详解 深入人心 里面的每一句话都令我印象深刻 我总结如下 很多论文给出了他们建议的网络结构 其中包括非常多的细节 比如
  • Oracle常用及非常用函数

    感于总有些网友提出一些非常基础的问题 比如有没有实现某某功能的函数啊 某某函数是做什么用的啊 格式是什么等等 同时也感受到自己对oracle函数认识的不足 于是集中月余时间专注于oracle函数 小有心得不敢私藏 发之与诸公共享 本文并不准
  • Java 使用BufferedImage快速画出图片

    Java 使用BufferedImage快速画出图片 在上一篇文章中我们学习了类似相机中的一些功能 比如黑白 马赛克等 但是我们发现一个问题 画的太慢了 一张图片能画半天 而且还是一条一条的 今天我们来学习如何迅速的画出图片 新知识 new
  • C++ 正则表达式regex(二)

    正则匹配 查找与替代 书写好模式字符串后 需要将待匹配的字符串和模式字符串进行一定规则的匹配 包括三种方式 匹配 regex match 查找 regex search 替换 regex replace 匹配很简单 直接将待匹配字符串和模式
  • PLSQL连接ORACLE时弹出空白框

    前两天一台数据库服务器坏掉了 重新找了台同型号的替换 服务器系统装好后 就在本地机器上远程操作服务器 配置数据库后 新部署的服务就是起不来 怀疑数据库的问题 就各种折腾 还是没有起作用 用本地PLSQL链接ORACLE时 就出现一个小白框
  • HBase选择Store file做compaction的算法

    The algorithm is basically as follows Run over the set of all store files from oldest to youngest If there are more than