Hbase MemStoreLAB

关于MemStore的补充

 

在通过HStore.addstore中添加一个kv时,首先把数据写入到memstore中。这一点没有什么说明;

 

publiclong add(final KeyValue kv) {

 

lock.readLock().lock();

 

try {

 

returnthis.memstore.add(kv);

 

} finally {

 

lock.readLock().unlock();

 

}

 

}

 

 

 

以上代码中调用memstore.add方法,

 

long add(final KeyValue kv) {

 

KeyValue toAdd = maybeCloneWithAllocator(kv);

 

return internalAdd(toAdd);

 

}

 

在上面的调用中,首先是通过maybeCloneWithAllocator去申请kv的内存。

 

private KeyValue maybeCloneWithAllocator(KeyValue kv) {

 

检查MemStoreLAB是否存在,如果不存在,表示没有配置MemStoreLAB

 

此配置通过hbase.hregion.memstore.mslab.enabled完成,默认值为true.

 

通过hbase.hregion.memstore.mslab.chunksize配置chunksize大小,默认值为2048*1024(2m),

 

个人认为,这块需要根据业务上的KV大小,去配置此大小,不然会导致空间的浪费

 

通过hbase.hregion.memstore.mslab.max.allocation配置单个KV的最大分配大小,默认为256*1024(256k)
如果单个KV的大小超过了指定的大小,直接在堆内存上生成。

 

MemStoreLAB(mslab)主要是为了解决memstore flush的内存碎片问题,而导致的java gc

 

hbase通过mslab每次向内存分配一个chunksize大小的块,所有的kv过来时,向此chunk中添加,

 

chunk不够时再重新申请一个新的chunk块。每次flush时,直接把占用的chunk块进行flush,

 

从而减少minor gc的发生频率。

 

if (allocator == null) {

 

return kv;

 

}

 

 

 

int len = kv.getLength();

 

检查kv是否超过了配置的单个大小,如果超过,不做处理,否则从一个chunk中得到一个allocation或者新生成一个chunk

 

Allocation alloc = allocator.allocateBytes(len);

 

if (alloc == null) {

 

// The allocation was too large, allocator decided

 

// not to do anything with it.

 

return kv;

 

}

 

assert alloc.getData() != null;

 

System.arraycopy(kv.getBuffer(), kv.getOffset(), alloc.getData(), alloc.getOffset(), len);

 

KeyValue newKv = new KeyValue(alloc.getData(), alloc.getOffset(), len);

 

newKv.setMvccVersion(kv.getMvccVersion());

 

return newKv;

 

}

 

 

 

memstore中通过internalAdd-->addToKVSet把一个kv添加到memstorekvset容器中,

 

此容器每一次的add操作都会进行排序操作,排序的比较器通过KeyValue.KVComparator来实现。

 

kvset是一个KeyValueSkipListSet的实例,此实例里面有一个ConcurrentSkipListMapmap容器。

 

每一次的add操作,都会把kv当成mapkeyvalue一起插入。

 

你可能感兴趣的:(MSLAB)