核心:Hbase是使用Java语言开发的,所以需要依赖于JVM。
Hbase的MemStore本质上是一块缓存,这就会面临Java的GC问题,在数据写入MemStore时,写入数据会产生内存碎片。并且RegionServer由多个Region组成,每一个Region根据列簇的个数多少具有相同数量的MemStore,MemStore的数据会混合在一起写入堆内存中(堆内存是共享的)。
二、过程分析- 上图中不同颜色方块表示4个Region
- 白色方块为可分配空间
当Region3执行flush *** 作将数据落入磁盘,蓝色区域被释放,为后续数据的写入分配空间,分配时会生成更小的内存空间。随着MemStore中的数据不断写入和flush,JVM会产生大量的内存碎片,导致最后无法给对象分配足够的空间,这时会触发Full GC来合并内存碎片。
三、优化:MSLABHbase使用了一种GC优化的技术,可以有效地减少Full GC的频率——MSLAB
- 每一个MemStore实例化得到一个MemStoreLAB实例
- MemStoreLAB申请一个2M的Chunk数组,维护一个偏移量Offset=0
- 每次一个Key-Value数据插入MemStore后,MemStoreLAB将这个数据转化成数组,复制到Chunk数组中,Offset随之增长
- Chunk满了后,再申请一个新的2M的Chunk数组。
优化点:此时如果进行flush *** 作,产生的内存碎片的粒度变粗(因为我flush释放掉的都是2M的Chunk数组,释放内存新产生的碎片也将大于等于2M)
四、深度优化:MemStoreChunkPoolMSLAB优化后,还存在一些问题。当Chunk数组写满后,会再申请一个Chunk数组,多次的申请会在新生代触发YongGC。可以对这种情况进行优化,将Chunk数组进行复用。
-
创建一个ChunkPool来管理未被引用的Chunk数组(这样不会被垃圾回收)
-
当Chunk数组不存在引用,放回Pool中
-
当ChunkPool达到最大容量,不再接受新的Chunk数组
-
如果需要Chunk数组,先去Pool中查看是否有可用的Chunk,没有则申请新Chunk数组
-
感觉有用的话,点个赞鼓励一下~
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)