HBase MSLAB

2019/08/13 HBase

HBase MSLAB

HBase MSLAB 作用:

MemStoreChunkPool 主要是为了减少 MemStore 导致的 GC 思路是提前申请好一堆 Chunk,默认 2MB 一个,然后将插入的小Cell 放到 Chunk 中存储。 hbase.hregion.memstore.mslab.max.allocation 这个参数决定cell小于多少,放入到Chunk中,默认是256*1024,即256K。 当对象超过256KB的话,就没有必要使用chunk来存了。

从而减少小对象不断GC带来的压力。

HBase MSLAB 参数以及初始化

RegionServer启动的时候,会调用 initializeMemStoreChunkCreator()方法初始化


  protected void initializeMemStoreChunkCreator() {
    //是否启用MSLBA ,配置为:hbase.hregion.memstore.mslab.enabled默认为true
    if (MemStoreLAB.isEnabled(conf)) {
      // MSLAB is enabled. So initialize MemStoreChunkPool
      // By this time, the MemstoreFlusher is already initialized. We can get the global limits from
      // it.
      //获取MemStore 全局最大内存配置,heap为:hbase.regionserver.global.memstore.size,默认为0.4*最大堆
      //如果启用了MemStore Offheap ,属性 hbase.regionserver.offheap.global.memstore.size是否大于0 来决定是否启用offheap,
      //默认为0,即不启用offheap memstore
      //
      Pair<Long, MemoryType> pair = MemorySizeUtil.getGlobalMemStoreSize(conf);
      long globalMemStoreSize = pair.getFirst();
      boolean offheap = this.regionServerAccounting.isOffheap();
      // When off heap memstore in use, take full area for chunk pool.
      //offheap为1,
      //heap 根据参数:hbase.hregion.memstore.chunkpool.maxsize 来定,这个默认是1.0。
      float poolSizePercentage = offheap? 1.0F:
          conf.getFloat(MemStoreLAB.CHUNK_POOL_MAXSIZE_KEY, MemStoreLAB.POOL_MAX_SIZE_DEFAULT);
      //初始化chunk的百分比,hbase.hregion.memstore.chunkpool.initialsize 默认是0,线上被设置为0.5,即初始化50%    
      float initialCountPercentage = conf.getFloat(MemStoreLAB.CHUNK_POOL_INITIALSIZE_KEY,
          MemStoreLAB.POOL_INITIAL_SIZE_DEFAULT);
      //chunk的大小,配置参数:hbase.hregion.memstore.mslab.chunksize,默认是2MB    
      int chunkSize = conf.getInt(MemStoreLAB.CHUNK_SIZE_KEY, MemStoreLAB.CHUNK_SIZE_DEFAULT);
      // init the chunkCreator
      //初始化chunk,初始化主要通过ChunkCreator 来实现
      ChunkCreator chunkCreator =
          ChunkCreator.initialize(chunkSize, offheap, globalMemStoreSize, poolSizePercentage,
      initialCountPercentage, this.hMemManager);
    }
  }
  

ChunkCreator chunk 的初始化

ChunkCreator 调用init然后会new 一个ChunkCreator,最终调用initializePools 来初始化, 讲解初始化之前,先介绍一下ChunkCreator的主要数据结构,方便理解 ChunkCrator 的主要数据结构如下:


  private Map<Integer, Chunk> chunkIdMap = new ConcurrentHashMap<Integer, Chunk>();

  private final boolean offheap;
  static ChunkCreator instance;

  static boolean chunkPoolDisabled = false;
  private MemStoreChunkPool dataChunksPool;
  private int chunkSize;
  private MemStoreChunkPool indexChunksPool;
  
  /**  chunkIdMap 创建的chunk的id和chunk对象的map
   offheap是否是offheap的
   instance  ChunkCreator 本身的示例全局只有一个
   chunkSize 一个chunk的大小默认为2MB2048*1024
   Chunk的pool分为
   dataChunksPool 默认占0.9
   indexChunksPool 默认占0.1,这块参数其实有问题后续说
   
   

类图:

Chunk分为heap和offheap 2种实现, Chunk 的数据结构是由data、id、size、fromPool data:数据类型为ByteBuffer,实际存储HBase 写入MemStore 数据的地方 id:一个标记id size:chunk 的大小 fromPool:是否存在pool中,通常都是true

MemStoreChunkPool label:便签,一般分为index和data chunkSize:由多少个Chunk maxCount:最大能容纳多少个Chunk,这个是根据算出来: maxCount = (int) (globalMemStoreSize * poolSizePercentage / chunkSize); reclaimedChunks:可取回的chunk,其实是一个阻塞队列 poolSizePercentage:比例

initialize 方法如下:

public static ChunkCreator initialize(int chunkSize, boolean offheap, long globalMemStoreSize,
                                        float poolSizePercentage, float initialCountPercentage,
                                        HeapMemoryManager heapMemoryManager) {
    if (instance != null) {
      return instance;
    }
    instance = new ChunkCreator(chunkSize, offheap, globalMemStoreSize, poolSizePercentage,
            initialCountPercentage, heapMemoryManager,
            MemStoreLABImpl.INDEX_CHUNK_PERCENTAGE_DEFAULT);
            //INDEX_CHUNK_PERCENTAGE_DEFAULT 这个地方写死了,虽然配置了hbase.hregion.memstore.mslab.indexchunksize
            //但是没用...可以改善一下,
    return instance;
  }

最后 ChunkCreator 调用了initializePools,初始化dataChunksPool和indexchunksPool


  private void initializePools(int chunkSize, long globalMemStoreSize,
                               float poolSizePercentage, float indexChunkSizePercentage,
                               float initialCountPercentage,
                               HeapMemoryManager heapMemoryManager) {
    //dataChunksPool的label为data,indexChunkSizePercentage 默认是0.1,
    //所以就是比例是(1-0.1)*1.0=0.9,initialCountPercentage默认为0,线上设置了0.5                           
    this.dataChunksPool = initializePool("data", globalMemStoreSize,
            (1 - indexChunkSizePercentage) * poolSizePercentage,
            initialCountPercentage, chunkSize, heapMemoryManager);
    // The index chunks pool is needed only when the index type is CCM.
    // Since the pools are not created at all when the index type isn't CCM,
    // we don't need to check it here.
     //dataChunksPool的label为index,indexChunkSizePercentage 默认是0.1,
    //所以就是比例是(1-0.1)*1.0=0.1,其它和dataChunksPool一致
    this.indexChunksPool = initializePool("index", globalMemStoreSize,
            indexChunkSizePercentage * poolSizePercentage,
            initialCountPercentage, (int) (indexChunkSizePercentage * chunkSize),
            heapMemoryManager);
  }

Search

    Post Directory