diff --git a/hbase-server/src/main/java/org/apache/hadoop/hbase/regionserver/CompactingMemStore.java b/hbase-server/src/main/java/org/apache/hadoop/hbase/regionserver/CompactingMemStore.java index 0ca8af0..344c2c7 100644 --- a/hbase-server/src/main/java/org/apache/hadoop/hbase/regionserver/CompactingMemStore.java +++ b/hbase-server/src/main/java/org/apache/hadoop/hbase/regionserver/CompactingMemStore.java @@ -277,6 +277,18 @@ public class CompactingMemStore extends AbstractMemStore { // Phase I: Update the pipeline getRegionServices().blockUpdates(); try { + if (!isActiveSizeAboveInMemFlushLimit()) { + // Many concurrent writing threads might see the memstore size above the flush limit and + // start the new thread. Consider 2 such threads in place. The 1st one got a chance and + // acquired the lock to block updates. It will push the active to pipeline and release the + // lock. At the same time there are other normal write threads trying to write cells to + // memstore. One such can get the region lock lock(read lock in such case). Then it will add + // cell(s) to fresh active segment in memstore. Now the 2nd thread for in memory flush(this + // thread) gets the lock and if below check is not there it will go ahead and push the + // current active segment to pipeline. This might be a very small segment and such an + // operation will be really unwanted. The below double check on size avoids such a case. + return; + } MutableSegment active = getActive(); if (LOG.isDebugEnabled()) { LOG.debug("IN-MEMORY FLUSH: Pushing active segment into compaction pipeline, " @@ -310,8 +322,12 @@ public class CompactingMemStore extends AbstractMemStore { return getRegionServices().getInMemoryCompactionPool(); } + private boolean isActiveSizeAboveInMemFlushLimit() { + return getActive().getSize() > inmemoryFlushSize; + } + private boolean shouldFlushInMemory() { - if(getActive().getSize() > inmemoryFlushSize) { + if (isActiveSizeAboveInMemFlushLimit()) { // size above flush threshold return (allowCompaction.get() && !inMemoryFlushInProgress.get()); }