HBase(七) HBase JAVA API - Filter
742
2022-05-28
使用HBase的现代产品对其读写性能的期望值不断提高。理想情况下,HBase应用程序希望在不放弃可靠的持久存储保证的情况下享受内存数据库的速度。我们在HBase 2.0中引入了一种名为Accordion的新算法,它朝着这个目标迈出了重要的一步。
HBase将数据划分为由RegionServer群集控制的region。 RegionServer的纵向可伸缩性对于最终用户的性能以及整个系统的利用率至关重要。通过更好地使用RAM,accordion提高了RegionServer的可伸缩性。它可以在内存中容纳更多数据,并减少写入磁盘的频率。这样带来多个好处。首先,降低了HBase的磁盘占用率和写入放大率。其次,更多的读写操作落到RAM,更少的操作落到磁盘I/O,换句话说,HBase的性能得以提高。传统上,这些指标被认为是不一致的,并且需要彼此进行权衡。使用accordion,它们会同时得到改善。
accordion的灵感来自于HBase的内部存储结构Log-Structured-Merge(LSM)树。 HBase region被存储为一系列可搜索键值映射。最顶部是一个可变的内存存储,称为MemStore,它保存最近的写入(put)操作。其余的是不可变的HDFS文件,称为HFiles。 MemStore溢出后,被刷新到磁盘,创建一个新的HFile。 HBase采用了多版本并发控制,即MemStore将数据变化存储为单独的版本。因此,一个key的多个版本可以在MemStore和多个HFile中。读取(get)操作通过key检索值,该操作扫描BlockCache中的HFile数据,以查找最新版本。为了减少磁盘访问次数,多个HFiles在后台被合并。此过程称为压缩(compaction),将删除冗余的cell并创建更大的文件。
accordion将LSM原理重新应用于MemStore,以消除数据仍在RAM中时的冗余和其他开销。这样做可以减少刷新到HDFS的频率,从而减少写放大和整个磁盘占用空间。由于MemStore溢出而产生的刷新减少,因而写操作停顿的频率降低,最后提高了写性能。磁盘上较少的数据还意味着对块缓存的压力较小,命中率较高,并最终改善了读取响应时间。最后,较少的磁盘写入也意味着在后台发生较少的压缩,即,从生产(读取和写入)工作中窃取了较少的周期。总而言之,可以将内存压缩的效果设想为一种催化剂,使整个系统运行起来更快。
accordion目前提供两种级别的内存压缩basic和eager。前者适用于所有数据更新模式的通用优化。后者对于数据流失率较高的应用程序(如生产者-消费者队列,购物车,共享计数器等)最有用。所有这些用例均具有频繁更新相同key的功能,这些key会生成多个冗余版本,算法可利用这些冗余版本提供更多价值。另一方面,eager优化可能会导致计算开销(更多的内存副本和垃圾回收),这可能会影响密集写入负载下的响应时间。如果MemStore使用on-heap的 MemStore-Local Allocation Buffer (MSLAB),则开销很高。建议不要将这种配置与eager压缩相结合。
在下一部分中,将了解有关Accordion压缩算法的更多详细信息。
如何使用
in-memory compaction可以全局配置,也可以按column family配置。 支持的级别为none(旧版实现),basic,eager。
默认情况下,所有表都应用basic in-memory compaction。 可以在hbase-site.xml中覆盖此全局配置,如下所示:
也可以在HBase Shell中按column family配置级别,如下所示:
create ‘
性能提升
我们通过流行的Yahoo Cloud Service Benchmark(YCSB)对HBase进行了广泛的压力测试。我们的实验使用了100-200 GB的数据集,并行使了各种代表性的工作负载。结果表明,Accordion可带来显着的性能提升。
Heavy-tailed (Zipf) 分布。第一个实验执行了一个工作负载,其中key使用Zipf分布,遵循大多数现实场景。在这种情况下,当100%为写时,Accordion最多可将写入放大率降低30%,将写入吞吐量提高20%,并将GC降低22%。50%为读时,读延迟减少了12%。
Uniform 分布。第二个实验执行了另一个工作负载,其中所有key都同样热度的。在这种情况下,100%为写时,Accordion可将写入放大率降低多达25%,将写入吞吐量提高50%,并将GC降低36%。读延迟不受影响(这是意料之中的,因为完全缺乏局部性)
Accordion是如何工作
高层设计。Accordion引入了CompactingMemStore一种内部应用压缩的MemStore实现。与默认的MemStore相比,后者将所有数据保持在一个整体的数据结构中,而Accordion将其作为一系列段进行管理。最年轻的部分称为活动部分,是可变的。它接受put操作。发生溢出时(默认情况下,为32MB-MemStore大小的25%),活动段将移动到内存管道中,并且变得不可变。我们称其为内存flush。 Get操作将扫描这些段和HFile(与HBase一样,可通过block cache访问后者)。
CompactingMemStore可能会不时在后台合并多个不可变的段,从而创建更大和更精简的段。因此,管道类似于“accordion bellows”(手风琴风箱),是“呼吸”(膨胀和收缩)的。
当RegionServer决定将一个或多个MemStore刷新到磁盘上以释放内存时,将会使用CompactingMemStore。这样做的理由是延长有效管理内存的MemStore的寿命,以减少总体I/O。当发生此类刷新时,所有管道段均移至复合snapshot,合并并流式传输到新的HFile。
段结构。 与默认的MemStore相似,CompactingMemStore在cell存储的顶部维护一个索引,以允许通过key快速搜索。 传统上,此索引被实现为Java跳表(ConcurrentSkipListMap)-动态但浪费的数据结构,用于管理许多小对象。 CompactingMemStore对不可变的段索引使用节省空间的扁平布局。 此通用优化可帮助所有压缩策略减少RAM开销,即使数据几乎没有冗余也是如此。 将段添加到管道后,索引被序列化为名为CellArrayMap的排序数组,该数组可以进行快速二分搜索。
CellArrayMap支持直接从Java堆分配cell,也支持从MSLAB的定制分配(堆上或堆外)。 通过从索引中引用的KeyValue对象可以抽象出实现上的差异。 CellArrayMap本身总是在堆上分配。
压缩算法。in-memory compaction 算法在流水线段的顶部维护单个扁平索引。这样可以节省空间,尤其是在数据项较小的情况下,因此可以更快的完成落盘操作。单个索引允许在一个位置进行搜索,因此控制住了读取延迟。
当活动段刷新到内存时,它进入到压缩管线队列中,并立即安排后台合并任务。后者同时扫描管道中的所有段(on-disk compaction),并将多个索引合并为一个。基本basic策略和eager压缩策略之间的差异体现在它们如何处理cell。basic压缩不会消除冗余数据版本,以避免物理复制。它只是重新排列对KeyValue对象的引用。相反,eager压缩会滤除重复项。这是以额外的计算和数据迁移为代价的-例如,使用MSLAB存储时,将尚存的cell复制到新创建的MSLAB。当数据高度冗余时,压缩的开销得到了回报。
压缩的未来实现可能会自动在basic和eager压缩策略之间进行选择。例如,该算法可能会尝试一次eager压缩,并根据收到的值(例如,被淘汰的部分数据)安排下一次压缩。这种方法可以减轻系统管理员的负担,并适应不断变化的访问模式。
摘要
在这篇博客中,我们讨论了Accordion的基本原理,配置,性能提升以及内存压缩算法的一些细节。 下一篇文章将重点为HBase开发人员介绍系统的内部。
我们感谢Michael Stack,Anoop Sam John和Ramkrishna Vasudevan的持续支持,使该项目得以实现。
云计算
版权声明:本文内容由网络用户投稿,版权归原作者所有,本站不拥有其著作权,亦不承担相应法律责任。如果您发现本站中有涉嫌抄袭或描述失实的内容,请联系我们jiasou666@gmail.com 处理,核实后本网站将在24小时内删除侵权内容。