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 刷新到磁盘的呢

相关推荐
morris1311 小时前
【redis】事务
数据库·redis·缓存·pipeline·lua·事务
Z_zz_Z___1 小时前
MySQL创建数据库和表,插入四大名著中的人物
数据库·mysql
月落星还在4 小时前
Redis 的过期策略与键的过期时间设置
数据库·redis·bootstrap
cg50177 小时前
MySQL数据库复杂的增删改查操作
数据库·mysql
虾球xz8 小时前
游戏引擎学习第147天
数据库·学习·游戏引擎
向上的车轮9 小时前
什么是时序数据库?有哪些时序数据库?常见的运用场景有哪些?
数据库·时序数据库
岱宗夫up10 小时前
【Python】Django 中的算法应用与实现
数据库·python·opencv·django·sqlite
比花花解语10 小时前
使用数据库和缓存的时候,是如何解决数据不一致的问题的?
数据库·缓存·数据一致性
YGGP11 小时前
Redis篇:基础知识总结与基于长期主义的内容更新
数据库·redis·缓存
KINICH ahau11 小时前
数据库1-2章
数据库·oracle