深刻理解HBase Memstore

MemStore是HBase很是重要的组成部分,深刻理解MemStore的运行机制、工做原理、相关配置,对HBase集群管理以及性能调优有很是重要的帮助。html

HBase Memstore

首先经过简单介绍HBase的读写过程来理解一下MemStore究竟是什么,在何处发挥做用,如何使用到以及为何要用MemStore。缓存

图一:Memstore Usage in HBase Read/Write Paths安全

当RegionServer(RS)收到写请求的时候(write request),RS会将请求转至相应的Region。每个Region都存储着一些列(a set of rows)。根据其列族的不一样,将这些列数据存储在相应的列族中(Column Family,简写CF)。不一样的CFs中的数据存储在各自的HStore中,HStore由一个Memstore及一系列HFile组成。Memstore位于RS的主内存中,而HFiles被写入到HDFS中。当RS处理写请求的时候,数据首先写入到Memstore,而后当到达必定的阀值的时候,Memstore中的数据会被刷到HFile中。网络

用到Memstore最主要的缘由是:存储在HDFS上的数据须要按照row key 排序。而HDFS自己被设计为顺序读写(sequential reads/writes),不容许修改。这样的话,HBase就不可以高效的写数据,由于要写入到HBase的数据不会被排序,这也就意味着没有为未来的检索优化。为了解决这个问题,HBase将最近接收到的数据缓存在内存中(in Memstore),在持久化到HDFS以前完成排序,而后再快速的顺序写入HDFS。须要注意的一点是实际的HFile中,不只仅只是简单地排序的列数据的列表,详见Apache HBase I/O – HFileide

除了解决“无序”问题外,Memstore还有一些其余的好处,例如:性能

  • 做为一个内存级缓存,缓存最近增长数据。一种显而易见的场合是,新插入数据老是比老数据频繁使用。优化

  • 在持久化写入以前,在内存中对Rows/Cells能够作某些优化。好比,当数据的version被设为1的时候,对于某些CF的一些数据,Memstore缓存了数个对该Cell的更新,在写入HFile的时候,仅须要保存一个最新的版本就行了,其余的均可以直接抛弃。this

有一点须要特别注意:每一次Memstore的flush,会为每个CF建立一个新的HFile。 在读方面相对来讲就会简单一些:HBase首先检查请求的数据是否在Memstore,不在的话就到HFile中查找,最终返回merged的一个结果给用户。spa

HBase Memstore关注要点

迫于如下几个缘由,HBase用户或者管理员须要关注Memstore而且要熟悉它是如何被使用的:设计

  • Memstore有许多配置能够调整以取得好的性能和避免一些问题。HBase不会根据用户本身的使用模式来调整这些配置,你须要本身来调整。

  • 频繁的Memstore flush会严重影响HBase集群读性能,并有可能带来一些额外的负载。

  • Memstore flush的方式有可能影响你的HBase schema设计

接下来详细讨论一下这些要点:

Configuring Memstore Flushes

对Memstore Flush来讲,主要有两组配置项:

  • 决定Flush触发时机

  • 决定Flush什么时候触发而且在Flush时候更新被阻断(block)

第一组是关于触发“普通”flush,这类flush发生时,并不影响并行的写请求。该类型flush的配置项有:

  • hbase.hregion.memstore.flush.size

< property >
  < name >hbase.hregion.memstore.flush.size</ name >
  < value >134217728</ value >
  < description >
  Memstore will be flushed to disk if size of the memstore
  exceeds this number of bytes. Value is checked by a thread that runs
  every hbase.server.thread.wakefrequency.
  </ description >
</ property >
  • base.regionserver.global.memstore.lowerLimit

< property >
  < name >hbase.regionserver.global.memstore.lowerLimit</ name >
  < value >0.35</ value >
  < description >Maximum size of all memstores in a region server before
  flushes are forced. Defaults to 35% of heap.
  This value equal to hbase.regionserver.global.memstore.upperLimit causes
  the minimum possible flushing to occur when updates are blocked due to
  memstore limiting.
  </ description >
</ property >

须要注意的是第一个设置是每一个Memstore的大小,当你设置该配置项时,你须要考虑一下每台RS承载的region总量。可能一开始你设置的该值比较小,后来随着region增多,那么就有可能由于第二个设置缘由Memstore的flush触发会变早许多。

第二组设置主要是出于安全考虑:有时候集群的“写负载”很是高,写入量一直超过flush的量,这时,咱们就但愿memstore不要超过必定的安全设置。在这种状况下,写操做就要被阻止(blocked)一直到memstore恢复到一个“可管理”(manageable)的大小。该类型flush配置项有:

  • hbase.regionserver.global.memstore.upperLimit

< property >
  < name >hbase.regionserver.global.memstore.upperLimit</ name >
  < value >0.4</ value >
  < description >Maximum size of all memstores in a region server before new
  updates are blocked and flushes are forced. Defaults to 40% of heap.
  Updates are blocked and flushes are forced until size of all memstores
  in a region server hits hbase.regionserver.global.memstore.lowerLimit.
  </ description >
</ property >
  •  hbase.hregion.memstore.block.multiplier

< property >
  < name >hbase.hregion.memstore.block.multiplier</ name >
  < value >2</ value >
  < description >
  Block updates if memstore has hbase.hregion.block.memstore
  time hbase.hregion.flush.size bytes. Useful preventing
  runaway memstore during spikes in update traffic. Without an
  upper-bound, memstore fills such that when it flushes the
  resultant flush files take a long time to compact or split, or
  worse, we OOME.
  </ description >
</ property >

某个节点“写阻塞”对该节点来讲影响很大,可是对于整个集群的影响更大。HBase设计为:每一个Region仅属于一个RS可是“写负载”是均匀分布于整个集群(全部Region上)。有一个如此“慢”的节点,将会使得整个集群都会变慢(最明显的是反映在速度上)。

提示严重关切Memstore的大小和Memstore Flush Queue的大小。理想状况下,Memstore的大小不该该达到hbase.regionserver.global.memstore.upperLimit的设置,Memstore Flush Queue 的size不能持续增加。

频繁的Memstore Flushes

要避免“写阻塞”,貌似让Flush操做尽可能的早于达到触发“写操做”的阈值为宜。可是,这将致使频繁的Flush操做,而由此带来的后果即是读性能降低以及额外的负载。

每次的Memstore Flush都会为每一个CF建立一个HFile。频繁的Flush就会建立大量的HFile。这样HBase在检索的时候,就不得不读取大量的HFile,读性能会受很大影响。

为预防打开过多HFile及避免读性能恶化,HBase有专门的HFile合并处理(HFile Compaction Process)。HBase会周期性的合并数个小HFile为一个大的HFile。明显的,有Memstore Flush产生的HFile越多,集群系统就要作更多的合并操做(额外负载)。更糟糕的是:Compaction处理是跟集群上的其余请求并行进行的。当HBase不可以跟上Compaction的时候(一样有阈值设置项),会在RS上出现“写阻塞”。像上面说到的,这是最最不但愿的。

提示严重关切RS上Compaction Queue 的size。要在其引发问题前,阻止其持续增大。

想了解更多HFile 建立和合并,可参看 Visualizing HBase Flushes And Compactions

理想状况下,在不超过hbase.regionserver.global.memstore.upperLimit的状况下,Memstore应该尽量多的使用内存(配置给Memstore部分的,而不是真个Heap的)。下图展现了一张“较好”的状况:

 “Somewhat”, because we could configure lower limit to be closer to upper, since we barely ever go over it.

说是“较好”,是由于咱们能够将“Lower limit”配置的更接近于“Upper limit”,咱们几乎不多有超过它。

Multiple Column Families & Memstore Flush

每次Memstore Flush,会为每一个CF都建立一个新的HFile。这样,不一样CF中数据量的不均衡将会致使产生过多HFile:当其中一个CF的Memstore达到阈值flush时,全部其余CF的也会被flush。如上所述,太频繁的flush以及过多的HFile将会影响集群性能。

提示不少状况下,一个CF是最好的设计

HLog (WAL) Size & Memstore Flush

第一张HBase Read/Write path图中,你可能已经注意到当数据被写入时会默认先写入Write-ahead Log(WAL)。WAL中包含了全部已经写入Memstore但还未Flush到HFile的更改(edits)。在Memstore中数据尚未持久化,当RegionSever宕掉的时候,可使用WAL恢复数据。

当WAL(在HBase中成为HLog)变得很大的时候,在恢复的时候就须要很长的时间。所以,对WAL的大小也有一些限制,当达到这些限制的时候,就会触发Memstore的flush。Memstore flush会使WAL 减小,由于数据持久化以后(写入到HFile),就没有必要在WAL中再保存这些修改。有两个属性能够配置:

  •  hbase.regionserver.hlog.blocksize

  • hbase.regionserver.maxlogs

你可能已经发现,WAL的最大值由hbase.regionserver.maxlogs * hbase.regionserver.hlog.blocksize (2GB by default)决定。一旦达到这个值,Memstore flush就会被触发。因此,当你增长Memstore的大小以及调整其余的Memstore的设置项时,你也须要去调整HLog的配置项。不然,WAL的大小限制可能会首先被触发,于是,你将利用不到其余专门为Memstore而设计的优化。抛开这些不说,经过WAL限制来触发Memstore的flush并不是最佳方式,这样作可能会会一次flush不少Region,尽管“写数据”是很好的分布于整个集群,进而颇有可能会引起flush“大风暴”。

提示:最好将hbase.regionserver.hlog.blocksize * hbase.regionserver.maxlogs 设置为稍微大于hbase.regionserver.global.memstore.lowerLimit * HBASE_HEAPSIZE.

Compression & Memstore Flush

HBase建议压缩存储在HDFS上的数据(好比HFiles)。除了节省硬盘空间,一样也会显著地减小硬盘和网络IO。使用压缩,当Memstore flush并将数据写入HDFS时候,数据会被压缩。压缩不会减慢多少flush的处理过程,却会大大减小以上所述问题,例如由于Memstore变大(超过 upper limit)而引发的“写阻塞”等等。

相关文章
相关标签/搜索