4. MemStore 接口
Memstore 的函数不能并行的被调用。调用者需要持有读写锁,这个的实现在HStore
中
我们放弃对MemStore中的诸多函数进行查看
直接看MemStore的实现类
- AbstractMemStore
- CompactingMemStore
- DefaultMemStore
4. 1 三个实现类的使用场景
1. AbstractMemStore
- 角色: 基础抽象类
- 作用 :
AbstractMemStore
是一个抽象基类,为HBase中的MemStore
实现提供了基本的框架和公共功能。它定义了MemStore
的核心操作,例如添加数据、获取数据、刷新数据等,但不具体实现这些操作的细节。- 它为子类提供了一些基础设施,例如管理内存中的数据结构、维护写入顺序和快照等。子类(如
CompactingMemStore
和DefaultMemStore
)基于这些基础功能,添加自己的具体实现。
- 总结 :
AbstractMemStore
是MemStore
实现的基类,它为不同类型的MemStore
实现提供了公共的功能和结构。它本身并不直接被使用,而是作为其他MemStore
实现的基础。
2. CompactingMemStore
(常用的一种MemStore类型)
- 角色 : 带有内存压缩功能的
MemStore
- 作用 :
CompactingMemStore
是MemStore
的一个实现,它在内存中实现了数据的压缩功能。内存压缩(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中,每个表可以有多个列族,每个列族的数据被单独存储。
- 数据写入流程 :
- 当数据写入HBase时,首先会写入到内存中的
MemStore
。 - 当
MemStore
的数据量达到一定阈值时,数据会被刷新(flush)到磁盘上,生成一个新的HFile。 HStore
负责管理这些HFile的生成和组织,并确保它们被正确地写入和读取。(真是文件的写入)
- 当数据写入HBase时,首先会写入到内存中的
2. 管理HFile的生命周期
-
合并与压缩(Compaction):
-
随着数据不断地写入和刷新,
HStore
会生成多个HFile。如果不进行管理,这些HFile的数量可能会增加,影响查询性能。 -
HStore
负责执行合并操作(Compaction),即将多个HFile合并成一个,以减少文件数量,优化读性能。 -
合并操作有两种类型:
Minor Compaction
(小合并)和
Major Compaction
(大合并)。
- Minor Compaction: 将少量小的HFile合并为一个较大的HFile,通常不会删除已删除的数据(tombstones)。
- Major Compaction: 将所有的HFile合并为一个,并清除过期或已删除的数据。
-
-
文件删除与清理:
- 在合并过程中,旧的HFile会被废弃。
HStore
负责安全地删除这些不再使用的HFile,释放磁盘空间。
- 在合并过程中,旧的HFile会被废弃。
3. 数据读取与查询
- 读取路径优化
- 当客户端请求读取数据时,
HStore
会从内存中的MemStore
和磁盘上的HFile中获取数据,并合并这些数据返回给客户端。 HStore
负责管理这些数据源的优先级和读取顺序,确保查询操作高效执行。
- 当客户端请求读取数据时,
- 数据版本管理
HStore
管理数据的多个版本(如果配置允许),可以根据查询的需求返回不同版本的数据。- 当进行读操作时,
HStore
会合并来自MemStore
和HFile的不同版本的数据,并根据查询的条件返回正确的结果。
4. 参与一致性与恢复机制
- 参与事务管理
- HBase支持简单的事务操作,例如原子增量、检查并设置(Check and Set)等。
HStore
在这些操作中,负责确保数据的一致性。
- HBase支持简单的事务操作,例如原子增量、检查并设置(Check and Set)等。
- 恢复机制
- 在系统崩溃或重启时,
HStore
参与数据的恢复操作,确保数据的一致性和完整性。
- 在系统崩溃或重启时,
5. MemStore与HFile的桥梁
HStore
在内存中的
MemStore
和持久化存储的HFile之间充当桥梁:
- 数据刷新(Flush) : 当
MemStore
满了时,HStore
负责将MemStore
中的数据持久化到HFile中。 - 读写均衡 :
HStore
既要确保高效的写入(通过MemStore
),也要确保高效的读取(通过合并和索引),在读写之间找到平衡。
6.2 这时候去找HStore 的写入数据流程
- 写一下随机生成数据插入数据的代码,每三秒插入一批数据 ✅
- 找一下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 刷新到磁盘的呢