HBase 源码阅读(四)HBase 关于LSM Tree的实现- MemStore

4. MemStore 接口

Memstore 的函数不能并行的被调用。调用者需要持有读写锁,这个的实现在HStore

我们放弃对MemStore中的诸多函数进行查看

直接看MemStore的实现类

  1. AbstractMemStore
  2. CompactingMemStore
  3. DefaultMemStore

4. 1 三个实现类的使用场景

1. AbstractMemStore

  • 角色: 基础抽象类
  • 作用 :
    • AbstractMemStore是一个抽象基类,为HBase中的MemStore实现提供了基本的框架和公共功能。它定义了MemStore的核心操作,例如添加数据、获取数据、刷新数据等,但不具体实现这些操作的细节。
    • 它为子类提供了一些基础设施,例如管理内存中的数据结构、维护写入顺序和快照等。子类(如CompactingMemStoreDefaultMemStore)基于这些基础功能,添加自己的具体实现。
  • 总结 : AbstractMemStoreMemStore实现的基类,它为不同类型的MemStore实现提供了公共的功能和结构。它本身并不直接被使用,而是作为其他MemStore实现的基础。

2. CompactingMemStore(常用的一种MemStore类型)

  • 角色 : 带有内存压缩功能的MemStore
  • 作用 :
    • CompactingMemStoreMemStore的一个实现,它在内存中实现了数据的压缩功能。内存压缩(Compaction)是一种优化技术,旨在减少内存占用和提高读性能。
    • 通过在内存中进行压缩,可以将多个冗余的版本合并,减少MemStore中的重复数据,从而降低内存的使用量。这有助于在数据写入频繁的情况下,减少内存压力并提高系统的整体性能。
    • 在数据被刷新到磁盘之前,CompactingMemStore会在内存中对数据进行部分整理,合并多个键值对的版本,删除过期的数据。这减少了写入HFile时的数据量,并在某种程度上提高了系统的读写性能。(我们不需要使用该类型)
  • 总结 : CompactingMemStore通过在内存中执行部分压缩操作,优化了MemStore的内存使用和数据写入性能。它适用于需要处理大量写入操作并且希望优化内存占用的场景。

3. DefaultMemStore(基础实现)

  • 角色 : 标准的MemStore实现
  • 作用 :
    • DefaultMemStore是HBase中MemStore的标准实现。它提供了基本的数据存储功能,将写入的所有数据保存在内存中,直到这些数据被刷新到磁盘。
    • CompactingMemStore不同,DefaultMemStore没有内存中的压缩功能。它直接按照数据写入的顺序存储数据,当MemStore达到阈值或系统资源不足时,会将数据刷新到HFile。
    • DefaultMemStore适用于不需要内存压缩的场景,特别是在数据更新频率不高或内存充足的情况下。
  • 总结 : DefaultMemStore是最基础的MemStore实现,适用于对性能和内存优化要求不高的场景。它提供了最直接的内存数据存储和管理方式

AbstractMemStore : 提供了MemStore实现的公共基础功能,是其他MemStore实现的基类。

CompactingMemStore: 实现了内存压缩功能,通过在内存中合并和整理数据,优化内存使用和系统性能。

DefaultMemStore : 标准的MemStore实现,提供了基础的数据存储功能,不包括内存压缩。适用于简单的数据存储需求。

4.2 系统如何指定自己所选择MemStore存储方式

在HBase中,可以通过配置文件或程序代码来指定所使用的MemStore存储方式。具体来说,你可以通过以下方式指定使用哪种MemStore实现:

1. 通过HBase配置文件配置

你可以在HBase的配置文件 hbase-site.xml 中指定使用的 MemStore 实现。配置文件中,相关的配置项是 hbase.regionserver.memstore.impl。以下是配置不同 MemStore 实现的示例:

  • 使用 DefaultMemStore(默认的 MemStore 实现):

    xml
    复制代码
    <property>
      <name>hbase.regionserver.memstore.impl</name>
      <value>org.apache.hadoop.hbase.regionserver.DefaultMemStore</value>
    </property>
    
  • 使用 CompactingMemStore(带内存压缩功能的 MemStore:

    xml
    复制代码
    <property>
      <name>hbase.regionserver.memstore.impl</name>
      <value>org.apache.hadoop.hbase.regionserver.CompactingMemStore</value>
    </property>
    
  • 使用自定义的 MemStore 实现 : 如果你有一个自定义的 MemStore 实现,可以将其类的完全限定名配置在 hbase.regionserver.memstore.impl 中:

    xml
    复制代码
    <property>
      <name>hbase.regionserver.memstore.impl</name>
      <value>com.example.hbase.CustomMemStore</value>
    </property>
    

4.3 DefaultMemStore

MemStore 保存对 Store 的内存修改。修改是单元。当要求刷新时,当前的 memstore 会移动到快照并被清除。我们继续从新的 memstore 和备份快照中提供编辑,直到刷新器报告刷新成功。此时我们让快照继续运行。

MemStore 函数不应并行调用。调用者应持有写入和读取锁。这是在 HStore 中完成的。

TODO:当我们删除项目时调整 memstore 的大小,因为它们已被删除。TODO:使用新的 KVSLS,需要确保我们根据 KV 大小的差异更新 HeapSize。

4.4 CompactingMemStore

是否使用内存压缩要看自己业务的场景,我们不涉及对某个key键的连续更新

支持内存压缩的 memstore 实现。在活动集和快照数据结构之间添加了一个压缩管道;它由要压缩的段列表组成。与快照一样,所有管道段都是只读的;更新仅影响活动集。为了确保此属性,我们利用现有的阻止机制------活动集被推送到管道,同时将区域的 updatesLock 保持在独占模式。定期在后台对所有管道段应用压缩,从而产生单个只读组件。当没有扫描仪读取"旧"段时,将丢弃它们。

5. DefaultMemStore的调用!

这时候还需要去找DefaultMemStore的调用历程,DefaultMemStore 出了在其类中实现外,外部调用的位置为HStore类

6. HStore

1. 管理数据的存储与组织

  • 列族管理 :
    • 在HBase中,每个表可以有多个列族,每个列族的数据被单独存储。HStore负责管理一个特定列族的数据。(这里可以测试一个列,多个列的分配地址,我们到底是怎么存储数据比较合适呢)
    • 对于每个列族,HStore管理该列族的所有存储文件(HFile)和内存中的MemStore
  • 数据写入流程 :
    • 当数据写入HBase时,首先会写入到内存中的MemStore
    • MemStore的数据量达到一定阈值时,数据会被刷新(flush)到磁盘上,生成一个新的HFile。
    • HStore负责管理这些HFile的生成和组织,并确保它们被正确地写入和读取。(真是文件的写入)

2. 管理HFile的生命周期

  • 合并与压缩(Compaction):

    • 随着数据不断地写入和刷新,HStore会生成多个HFile。如果不进行管理,这些HFile的数量可能会增加,影响查询性能。

    • HStore负责执行合并操作(Compaction),即将多个HFile合并成一个,以减少文件数量,优化读性能。

    • 合并操作有两种类型:

      Minor Compaction

      (小合并)和

      Major Compaction

      (大合并)。

      • Minor Compaction: 将少量小的HFile合并为一个较大的HFile,通常不会删除已删除的数据(tombstones)。
      • Major Compaction: 将所有的HFile合并为一个,并清除过期或已删除的数据。
  • 文件删除与清理:

    • 在合并过程中,旧的HFile会被废弃。HStore负责安全地删除这些不再使用的HFile,释放磁盘空间。

3. 数据读取与查询

  • 读取路径优化
    • 当客户端请求读取数据时,HStore会从内存中的MemStore和磁盘上的HFile中获取数据,并合并这些数据返回给客户端。
    • HStore负责管理这些数据源的优先级和读取顺序,确保查询操作高效执行。
  • 数据版本管理
    • HStore管理数据的多个版本(如果配置允许),可以根据查询的需求返回不同版本的数据。
    • 当进行读操作时,HStore会合并来自MemStore和HFile的不同版本的数据,并根据查询的条件返回正确的结果。

4. 参与一致性与恢复机制

  • 参与事务管理
    • HBase支持简单的事务操作,例如原子增量、检查并设置(Check and Set)等。HStore在这些操作中,负责确保数据的一致性。
  • 恢复机制
    • 在系统崩溃或重启时,HStore参与数据的恢复操作,确保数据的一致性和完整性。

5. MemStore与HFile的桥梁

  HStore

在内存中的

  MemStore

和持久化存储的HFile之间充当桥梁:

  • 数据刷新(Flush) : 当MemStore满了时,HStore负责将MemStore中的数据持久化到HFile中。
  • 读写均衡 : HStore既要确保高效的写入(通过MemStore),也要确保高效的读取(通过合并和索引),在读写之间找到平衡。

6.2 这时候去找HStore 的写入数据流程

  1. 写一下随机生成数据插入数据的代码,每三秒插入一批数据 ✅
  2. 找一下HStore 写入到MemStore的代码

7. HStore 写入MemStore

7.1 add方法

java 复制代码
  public void add(final Iterable<Cell> cells, MemStoreSizing memstoreSizing) {
    lock.readLock().lock();
    try {
      if (this.currentParallelPutCount.getAndIncrement() > this.parallelPutCountPrintThreshold) {
        LOG.trace(this.getTableName() + "tableName={}, encodedName={}, columnFamilyName={} is " +
            "too busy!", this.getRegionInfo().getEncodedName(), this .getColumnFamilyName());
      }
      memstore.add(cells, memstoreSizing);
    } finally {
      lock.readLock().unlock();
      currentParallelPutCount.decrementAndGet();
    }
  }

此时就设计另一个问题,MemStore如何Flush 刷新到磁盘的呢

相关推荐
MonkeyKing_sunyuhua8 分钟前
ubuntu22.04 docker-compose安装postgresql数据库
数据库·docker·postgresql
天郁青8 分钟前
数据库交互的本地项目:后台管理系统
数据库·交互
马剑威(威哥爱编程)14 分钟前
MongoDB面试专题33道解析
数据库·mongodb·面试
小光学长39 分钟前
基于vue框架的的流浪宠物救助系统25128(程序+源码+数据库+调试部署+开发环境)系统界面在最后面。
数据库·vue.js·宠物
零炻大礼包1 小时前
【SQL server】数据库远程连接配置
数据库
zmgst2 小时前
canal1.1.7使用canal-adapter进行mysql同步数据
java·数据库·mysql
随心............2 小时前
python操作MySQL以及SQL综合案例
数据库·mysql
€☞扫地僧☜€2 小时前
docker 拉取MySQL8.0镜像以及安装
运维·数据库·docker·容器
CopyDragon2 小时前
设置域名跨越访问
数据库·sqlite
xjjeffery2 小时前
MySQL 基础
数据库·mysql