diff --git a/hbase-server/src/main/java/org/apache/hadoop/hbase/regionserver/HRegion.java b/hbase-server/src/main/java/org/apache/hadoop/hbase/regionserver/HRegion.java index 18024d9..cea384e 100644 --- a/hbase-server/src/main/java/org/apache/hadoop/hbase/regionserver/HRegion.java +++ b/hbase-server/src/main/java/org/apache/hadoop/hbase/regionserver/HRegion.java @@ -38,6 +38,7 @@ import java.util.Map; import java.util.Map.Entry; import java.util.NavigableMap; import java.util.NavigableSet; +import java.util.Random; import java.util.RandomAccess; import java.util.Set; import java.util.TreeMap; @@ -561,6 +562,8 @@ public class HRegion implements HeapSize, PropagatingConfigurationObserver, Regi long memstoreFlushSize; final long timestampSlop; + private volatile long lastFlushTime; + private long flushJitterTime; final long rowProcessorTimeout; // Last flush time for each Store. Useful when we are flushing for each column @@ -853,6 +856,14 @@ public class HRegion implements HeapSize, PropagatingConfigurationObserver, Regi this.lastStoreFlushTimeMap.put(store, lastFlushTime); } + + this.lastFlushTime = EnvironmentEdgeManager.currentTime(); + if (this.flushCheckInterval > 0) + // Initialize the flushJitter time at region open time, this random value is fixed for each + // region. Therefore, the flush across all regions are uniformly distributed, even after a + // table flush operation. + flushJitterTime = (long)(new Random()).nextInt((int)this.flushCheckInterval); + // Use maximum of log sequenceid or that which was found in stores // (particularly if no recovered edits, seqid will be -1). long nextSeqid = maxSeqId; @@ -1630,6 +1641,11 @@ public class HRegion implements HeapSize, PropagatingConfigurationObserver, Regi return fs.getFileSystem(); } + /** @return the last time the region was flushed */ + public long getLastFlushTime() { + return this.lastFlushTime; + } + /** @return the {@link HRegionFileSystem} used by this region */ public HRegionFileSystem getRegionFileSystem() { return this.fs; @@ -1974,7 +1990,7 @@ public class HRegion implements HeapSize, PropagatingConfigurationObserver, Regi * Should the store be flushed because it is old enough. *

* Every FlushPolicy should call this to determine whether a store is old enough to flush(except - * that you always flush all stores). Otherwise the {@link #shouldFlush()} method will always + * that you always flush all stores). Otherwise the {@link #shouldFlushStore()} method will always * returns true which will make a lot of flush requests. */ boolean shouldFlushStore(Store store) { @@ -1992,6 +2008,11 @@ public class HRegion implements HeapSize, PropagatingConfigurationObserver, Regi return false; } long now = EnvironmentEdgeManager.currentTime(); + // the flushInterval has a randomized flushJitterTime added to it, so every region will be + // flushed at different time even the lastFlushtime are same for all regions + if (now - getLastFlushTime() < flushCheckInterval + flushJitterTime) { + return false; + } if (store.timeOfOldestEdit() < now - this.flushCheckInterval) { if (LOG.isDebugEnabled()) { LOG.debug("Flush column family: " + store.getColumnFamilyName() + " of " + @@ -7659,7 +7680,7 @@ public class HRegion implements HeapSize, PropagatingConfigurationObserver, Regi ClassSize.OBJECT + ClassSize.ARRAY + 44 * ClassSize.REFERENCE + 3 * Bytes.SIZEOF_INT + - (14 * Bytes.SIZEOF_LONG) + + (16 * Bytes.SIZEOF_LONG) + 5 * Bytes.SIZEOF_BOOLEAN); // woefully out of date - currently missing: