HBase2.0新特性之In-Memory Compaction

本文涉及的产品
云原生多模数据库 Lindorm,多引擎 多规格 0-4节点
云数据库 Redis 版,社区版 2GB
推荐场景:
搭建游戏排行榜
云数据库 MongoDB,通用型 2核4GB
简介: In-Memory Compaction是HBase2.0中的重要特性之一,通过在内存中引入LSM结构,减少多余数据,实现降低flush频率和减小写放大的效果。本文根据HBase2.0中相关代码以及社区的讨论、博客,介绍In-Memory Compaction的使用和实现原理。

In-Memory Compaction是HBase2.0中的重要特性之一,通过在内存中引入LSM结构,减少多余数据,实现降低flush频率和减小写放大的效果。本文根据HBase2.0中相关代码以及社区的讨论博客,介绍In-Memory Compaction的使用和实现原理。

原理

概念和数据结构

In-Memory Compaction中引入了MemStore的一个新的实现类 CompactingMemStore 。顾名思义,这个类和默认memstore的区别在于实现了在内存中compaction。

CompactingMemStore中,数据以 segment 作为单位进行组织,一个memStore中包含多个segment。数据写入时首先进入一个被称为 active 的segment,这个segment是可修改的。当active满之后,会被移动到 pipeline 中,这个过程称为 in-memory flush 。pipeline中包含多个segment,其中的数据不可修改。CompactingMemStore会在后台将pipeline中的多个segment合并为一个更大、更紧凑的segment,这就是compaction的过程。
如果RegionServer需要把memstore的数据flush到磁盘,会首先选择其他类型的memstore,然后再选择CompactingMemStore。这是因为CompactingMemStore对内存的管理更有效率,所以延长CompactingMemStore的生命周期可以减少总的I/O。当CompactingMemStore被flush到磁盘时,pipeline中的所有segment会被移到一个snapshot中进行合并然后写入HFile。
image

在默认的MemStore中,对cell的索引使用ConcurrentSkipListMap,这种结构支持动态修改,但是其中存在大量小对象,内存浪费比较严重。而在CompactingMemStore中,由于pipeline里面的数据是只读的,就可以使用更紧凑的数据结构来存储索引,减少内存使用。代码中使用CellArrayMap结构来存储cell索引,其内部实现是一个数组。
image

compaction策略

当一个active segment被flush到pipeline中之后,后台会触发一个任务对pipeline中的数据进行合并。合并任务会对pipeline中所有segment进行scan,将他们的索引合并为一个。有三种合并策略可供选择:Basic,Eager,Adaptive。
Basic compaction策略和Eager compaction策略的区别在于如何处理cell数据。Basic compaction不会清理多余的数据版本,这样就不需要对cell的内存进行拷贝。而Eager compaction会过滤重复的数据,并清理多余的版本,这意味着会有额外的开销:例如如果使用了MSLAB存储cell数据,就需要把经过清理之后的cell从旧的MSLAB拷贝到新的MSLAB。basic适用于所有写入模式,eager则主要针对数据大量淘汰的场景:例如消息队列、购物车等。
Adaptive策略则是根据数据的重复情况来决定是否使用Eager策略。在Adaptive策略中,首先会对待合并的segment进行评估,方法是在已经统计过不重复key个数的segment中,找出cell个数最多的一个,然后用这个segment的numUniqueKeys / getCellsCount得到一个比例,如果比例小于设定的阈值,则使用Eager策略,否则使用Basic策略。

使用

配置

2.0中,默认的In-Memory Compaction策略为basic。可以通过修改hbase-site.xml修改:

<property>
 <name>hbase.hregion.compacting.memstore.type</name>
 <value><none|basic|eager|adaptive></value>
 </property>

也可以单独设置某个列族的级别:

create ‘<tablename>’, 
{NAME => ‘<cfname>’, IN_MEMORY_COMPACTION => ‘<NONE|BASIC|EAGER|ADAPTIVE>’}

性能提升

社区的博客中给出了两个不同场景的测试结果。使用YCSB测试工具,100-200 GB数据集。分别在key热度符合Zipf分布和平均分布两种情况下,测试了只有写操作情况下写放大、吞吐、GC相比默认memstore的变化,以及读写各占50%情况下尾部读延时的变化。
测试结果如下表:

key热度分布 写放大 吞吐 GC 尾部读延时
Zipf 30%↓ 20% ↑ 22% ↓ 12% ↓
平均分布 25%↓ 50% ↑ 36% ↓ 无变化

钉钉扫码关注hbase技术交流群,敬请期待。
jiaoliuqun
最后播报一下,云HBase2.0 在2018年6月6日将正式发布,点击了解更多
hbase20_jpeg

目录
相关文章
|
4月前
|
设计模式 SQL 分布式计算
Spark Day06:Spark Core之Spark 内核调度和SparkSQL快速入门
Spark Day06:Spark Core之Spark 内核调度和SparkSQL快速入门
43 0
|
2月前
|
SQL 数据处理 Apache
Flink报错问题之Flink报错Only a single 'INSERT INTO' is supported如何解决
Flink报错通常是指在使用Apache Flink进行实时数据处理时遇到的错误和异常情况;本合集致力于收集Flink运行中的报错信息和解决策略,以便开发者及时排查和修复问题,优化Flink作业的稳定性。
|
SQL 分布式计算 Java
flink报错踩坑:org.apache.flink.table.catalog.hive.client.HiveShimV100.registerTemporaryFunction
当想使用本地开发环境运行flink读写线上hive数据来运行时报错。我使用maven管理的开发环境依赖。由于代码发布到测试环境集群上跑时并没有报错,而测试环境对应的依赖都是使用放在上面的依赖jar的,并不使用本地maven管理的依赖(也就是没有打入项目jar)。所以我猜测是本地运行环境依赖有问题,也就是项目中maven的pom文件的依赖有问题。
355 0
flink报错踩坑:org.apache.flink.table.catalog.hive.client.HiveShimV100.registerTemporaryFunction
|
Shell 分布式数据库 Android开发
HBase的Dead节点问题&&Hbase创建表时报“org.apache.hadoop.hbase.PleaseHoldException: Master is initializing”错误
HBase的Dead节点问题&&Hbase创建表时报“org.apache.hadoop.hbase.PleaseHoldException: Master is initializing”错误
172 0
HBase的Dead节点问题&&Hbase创建表时报“org.apache.hadoop.hbase.PleaseHoldException: Master is initializing”错误
|
JSON 分布式计算 Hadoop
Structured_Source_HDFS_Spark 代码 | 学习笔记
快速学习 Structured_Source_HDFS_Spark 代码
83 0
|
SQL 分布式计算 Java
spark 对于hive metastore的兼容性随笔--通过classloader实现
spark 对于hive metastore的兼容性随笔--通过classloader实现
407 0
|
SQL 存储 缓存
EMR Spark-SQL性能极致优化揭秘 Native Codegen Framework
EMR团队探索并开发了SparkSQL Native Codegen框架,为SparkSQL换了引擎,新引擎带来最高4倍性能提升,为EMR再次获取世界第一立下汗马功劳。来自阿里云EMR团队的周克勇将详细介绍Native Codegen框架。
EMR Spark-SQL性能极致优化揭秘 Native Codegen Framework
|
SQL 分布式计算 Java
EMR Spark-SQL性能极致优化揭秘 Native Codegen Framework
SparkSQL多年来的性能优化集中在Optimizer和Runtime两个领域。前者的目的是为了获得最优的执行计划,后者的目的是针对既定的计划尽可能执行的更快。
 EMR Spark-SQL性能极致优化揭秘 Native Codegen Framework
|
分布式计算 分布式数据库 Spark
|
存储 SQL 分布式计算
EMR Spark Runtime Filter性能优化
Join是一个非常耗费资源耗费时间的操作,特别是数据量很大的情况下。一般流程上会涉及底层表的扫描/shuffle/Join等过程, 如果我们能够尽可能的在靠近源头上减少参与计算的数据,一方面可以提高查询性能,另一方面也可以减少资源的消耗(网络/IO/CPU等),在同样的资源的情况下可以支撑更多的查询。