hbase memstorelab

时间:2024-06-01 23:35:44

关于MemStore的补充

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

publiclongadd(finalKeyValue
kv) {

lock.readLock().lock();

try{

returnthis.memstore.add(kv);

}finally{

lock.readLock().unlock();

}

}

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

longadd(finalKeyValue
kv) {

KeyValue toAdd =maybeCloneWithAllocator(kv);

returninternalAdd(toAdd);

}

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

privateKeyValue 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)主要是为了解决memstoreflush的内存碎片问题,而导致的javagc。

hbase通过mslab每次向内存分配一个chunksize大小的块,全部的kv过来时,向此chunk中加入�,

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

从而降低minorgc的发生频率。

if(allocator==
null){

returnkv;

}

intlen = 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.

returnkv;

}

assertalloc.getData() !=
null;

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

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

newKv.setMvccVersion(kv.getMvccVersion());

returnnewKv;

}

在memstore中通过internalAdd-->addToKVSet把一个kv加入�到memstore听kvset容器中,

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

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

每一次的add操作,都会把kv当成map的key与value一起插入。