MemStoreChunkPool&MSLAB提升HBASE GC性能

          

        Jvm使用过程中,一个比较重要的概念就是GC,Hbase是使用JAVA语言开发的,JVM的GC优化也是比较重要的一个优化方法。Hbase中对于写的数据key/value大小不固定,有可能有很对比较小即大小的key/value,就有很大的概率产生jvm内存碎片问题。举个例子:    

      当Jvm new一个2K大小的对象,JVM将无从heap分配它,因为找不到连续可用的内存空间来容纳这个对象,就算Heap当时还有500M的剩余空间,也无能为力。最终,JVM会选择触发Full GC重新压缩内存使之连续,然后再分配。

即触发Full GC,并不只有在内存满或达到触发比例的时候,还有可能是因为内存碎片。

产生内存碎片的主要原因是:

  • 分配的大小不一。
  • 分配的空间不连续。

如何检测因内存碎片触发了Full GC?
通过启动jvm时,添加 -XX:PrintFLSStatistics=1 参数来打印每次gc前后的Heap余量。较大的余量,可以怀疑Heap中存在内存碎片过多。
另外这篇blog有更详细的图文解释:

http://www.cloudera.com/blog/2011/02/avoiding-full-gcs-in-hbase-with-memstore-local-allocation-buffers-part-2/


下图是hbase在memstore产生jvm 碎片问题示意图。


     

           Arena Allocation,是一种GC优化技术,它可以有效地减少因内存碎片导致的Full GC,从而提高系统的整体性能。MemStore-Local Allocation Buffers就是其在其在Hbase中的应用。

          MemStore-Local Allocation Buffers通过预先分配内存块的方式解决了因为内存碎片造成的Full GC问题,但是对于频繁更新操作的时候,MemStore被flush到文件系统时没有reference的chunk还是会触发很多的Young GC。所以HBase-8163提出了MemStoreChunkPool的概念,也就是由HBase来管理一个ChunkPool用来存放chunk,不再依赖JVM的GC。这个ticket的本质也是由HBase进程来管理内存分配和重分配,不再依赖于Java GC。

       

MemStore-Local Allocation Buffer:

Ø每个MemStore都有一个MemStoreLAB实例

ØMemStoreLAB有一个2MB的curChunk,其nextFreeOffset为0

Ø每次insert一个KV时,数据(byte[]数组)复制到curChunk,nextFreeOffset随之增长

ØcurChunk满了以后,重新分配一个2MB的Chunk

Ø上述操作采用compare-and-swap[cas],因此无需加锁

优点: 

           a、原始插入的数据生命周期变短,就不用进入年老代

           b、可能进入年老代的Chunk是固定以2MB为大小,消除碎片的烦恼

           c、 每个Chunk只可能属于一个MemStore

           d、当MemStore刷到磁盘,Heap释放的内存也是以2MB为单位。

几个重要的配置:

hbase.hregion.memstore.mslab.enabled

      是否启用MSLAB,默认true

hbase.hregion.memstore.mslab.chunksize

         Chunk的尺寸,默认2MB

hbase.hregion.memstore.mslab.max.allocation

       MSLAB中单次分配内存的最大尺寸,默认256K,超过该尺寸的内存直接在Heap上分配。【当key/value大小大于256k,认为不是内存碎片】。



MemStoreChunkPool 介绍:

MemStoreChunkPool&MSLAB提升HBASE GC性能_第1张图片

Solution:
1.Create a chunk pool to manage the no-reference chunks, instead of being reclaimed by JVM
2.When a Chunk has no reference, put it back to the pool
3.The pool has a max capacity, it will skip the chunks when achieve the max size
4.When we need new Chunk to store KeyValue, get it from the pool if exists, else create new one by pool, so we could be able to reuse the old chunks


  


你可能感兴趣的:(jvm,优化,alloc,MemStore-Local)