You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@hbase.apache.org by ns...@apache.org on 2011/10/11 04:14:41 UTC

svn commit: r1181507 - in /hbase/branches/0.89/src: main/java/org/apache/hadoop/hbase/regionserver/ test/java/org/apache/hadoop/hbase/ test/java/org/apache/hadoop/hbase/regionserver/

Author: nspiegelberg
Date: Tue Oct 11 02:14:39 2011
New Revision: 1181507

URL: http://svn.apache.org/viewvc?rev=1181507&view=rev
Log:
Avoid the static variable global mem store size in HRegion.

Summary:
I found an easy way to avoid the static variable global mem store size in the
HRegion.

Every time when the RS detect a new region, set the reference of this RS to
this region.

I aslo add a unit test for this case

Test Plan:
Passing the unit tests

Reviewed By: kannan
Reviewers: jgray, nspiegelberg, dhruba, kannan
CC: awolff, kannan, hbase@lists,
Tasks:
#503382: put latency in prod cluster

Revert Plan:
OK

Differential Revision: 228061

Added:
    hbase/branches/0.89/src/test/java/org/apache/hadoop/hbase/TestGlobalMemStoreSize.java
Modified:
    hbase/branches/0.89/src/main/java/org/apache/hadoop/hbase/regionserver/HRegion.java
    hbase/branches/0.89/src/main/java/org/apache/hadoop/hbase/regionserver/HRegionServer.java
    hbase/branches/0.89/src/main/java/org/apache/hadoop/hbase/regionserver/MemStoreFlusher.java
    hbase/branches/0.89/src/test/java/org/apache/hadoop/hbase/regionserver/TestHRegion.java

Modified: hbase/branches/0.89/src/main/java/org/apache/hadoop/hbase/regionserver/HRegion.java
URL: http://svn.apache.org/viewvc/hbase/branches/0.89/src/main/java/org/apache/hadoop/hbase/regionserver/HRegion.java?rev=1181507&r1=1181506&r2=1181507&view=diff
==============================================================================
--- hbase/branches/0.89/src/main/java/org/apache/hadoop/hbase/regionserver/HRegion.java (original)
+++ hbase/branches/0.89/src/main/java/org/apache/hadoop/hbase/regionserver/HRegion.java Tue Oct 11 02:14:39 2011
@@ -157,8 +157,9 @@ public class HRegion implements HeapSize
   // private int [] storeSize = null;
   // private byte [] name = null;
 
-  final AtomicLong memstoreSize = new AtomicLong(0);
-  static final AtomicLong globalMemstoreSize = new AtomicLong(0);
+  protected final AtomicLong memstoreSize = new AtomicLong(0);
+
+  private HRegionServer regionServer = null;
 
   /**
    * The directory for the table this region is part of.
@@ -442,6 +443,19 @@ public class HRegion implements HeapSize
     }
   }
 
+  public AtomicLong getMemstoreSize() {
+    return memstoreSize;
+  }
+
+  public HRegionServer getRegionServer() {
+    return regionServer;
+  }
+
+  public void setRegionServer(HRegionServer regionServer) {
+    this.regionServer = regionServer;
+    regionServer.getGlobalMemstoreSize().getAndAdd(this.memstoreSize.get());
+  }
+
   /**
    * Increase the size of mem store in this region and the sum of global mem
    * stores' size
@@ -449,15 +463,11 @@ public class HRegion implements HeapSize
    * @return the size of memstore in this region
    */
   public long incMemoryUsage(long memStoreSize) {
-    globalMemstoreSize.addAndGet(memStoreSize);
+    if (this.regionServer != null)
+      this.regionServer.getGlobalMemstoreSize().addAndGet(memStoreSize);
     return this.memstoreSize.addAndGet(memStoreSize);
   }
 
-  /** @return the sum of global mem store size */
-  public static long getGlobalMemstoreSize() {
-    return globalMemstoreSize.get();
-  }
-
   /** @return a HRegionInfo object for this region */
   public HRegionInfo getRegionInfo() {
     return this.regionInfo;

Modified: hbase/branches/0.89/src/main/java/org/apache/hadoop/hbase/regionserver/HRegionServer.java
URL: http://svn.apache.org/viewvc/hbase/branches/0.89/src/main/java/org/apache/hadoop/hbase/regionserver/HRegionServer.java?rev=1181507&r1=1181506&r2=1181507&view=diff
==============================================================================
--- hbase/branches/0.89/src/main/java/org/apache/hadoop/hbase/regionserver/HRegionServer.java (original)
+++ hbase/branches/0.89/src/main/java/org/apache/hadoop/hbase/regionserver/HRegionServer.java Tue Oct 11 02:14:39 2011
@@ -48,6 +48,7 @@ import java.util.concurrent.LinkedBlocki
 import java.util.concurrent.TimeUnit;
 import java.util.concurrent.atomic.AtomicBoolean;
 import java.util.concurrent.atomic.AtomicInteger;
+import java.util.concurrent.atomic.AtomicLong;
 import java.util.concurrent.locks.ReentrantReadWriteLock;
 
 import org.apache.commons.cli.CommandLine;
@@ -247,6 +248,8 @@ public class HRegionServer implements HR
   private Replication replicationHandler;
   // End of replication
 
+  private final AtomicLong globalMemstoreSize = new AtomicLong(0);
+
   /**
    * Starts a HRegionServer at the default location
    * @param conf
@@ -748,6 +751,10 @@ public class HRegionServer implements HR
     }
   }
 
+  public AtomicLong getGlobalMemstoreSize() {
+    return globalMemstoreSize;
+  }
+
   /*
    * @param r Region to get RegionLoad for.
    * @return RegionLoad instance.
@@ -1456,6 +1463,7 @@ public class HRegionServer implements HR
       this.lock.writeLock().lock();
       try {
         this.onlineRegions.put(mapKey, region);
+        region.setRegionServer(this);
       } finally {
         this.lock.writeLock().unlock();
       }

Modified: hbase/branches/0.89/src/main/java/org/apache/hadoop/hbase/regionserver/MemStoreFlusher.java
URL: http://svn.apache.org/viewvc/hbase/branches/0.89/src/main/java/org/apache/hadoop/hbase/regionserver/MemStoreFlusher.java?rev=1181507&r1=1181506&r2=1181507&view=diff
==============================================================================
--- hbase/branches/0.89/src/main/java/org/apache/hadoop/hbase/regionserver/MemStoreFlusher.java (original)
+++ hbase/branches/0.89/src/main/java/org/apache/hadoop/hbase/regionserver/MemStoreFlusher.java Tue Oct 11 02:14:39 2011
@@ -287,7 +287,7 @@ class MemStoreFlusher extends Thread imp
    * amount of memstore consumption.
    */
   public synchronized void reclaimMemStoreMemory() {
-    if ( HRegion.getGlobalMemstoreSize() >= globalMemStoreLimit) {
+    if ( this.server.getGlobalMemstoreSize().get() >= globalMemStoreLimit) {
       flushSomeRegions();
     }
   }
@@ -301,7 +301,7 @@ class MemStoreFlusher extends Thread imp
     ArrayList<HRegion> regionsToCompact = new ArrayList<HRegion>();
     for (SortedMap<Long, HRegion> m =
         this.server.getCopyOfOnlineRegionsSortedBySize();
-      (globalMemStoreSize = HRegion.globalMemstoreSize.get()) >=
+      (globalMemStoreSize = this.server.getGlobalMemstoreSize().get()) >=
         this.globalMemStoreLimitLowMark;) {
       // flush the region with the biggest memstore
       if (m.size() <= 0) {

Added: hbase/branches/0.89/src/test/java/org/apache/hadoop/hbase/TestGlobalMemStoreSize.java
URL: http://svn.apache.org/viewvc/hbase/branches/0.89/src/test/java/org/apache/hadoop/hbase/TestGlobalMemStoreSize.java?rev=1181507&view=auto
==============================================================================
--- hbase/branches/0.89/src/test/java/org/apache/hadoop/hbase/TestGlobalMemStoreSize.java (added)
+++ hbase/branches/0.89/src/test/java/org/apache/hadoop/hbase/TestGlobalMemStoreSize.java Tue Oct 11 02:14:39 2011
@@ -0,0 +1,174 @@
+/**
+ * Copyright 2008 The Apache Software Foundation
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional infomation
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.hadoop.hbase;
+
+import java.io.IOException;
+import java.util.List;
+import java.util.ArrayList;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+
+import org.apache.hadoop.hbase.client.HTable;
+import org.apache.hadoop.hbase.client.Put;
+
+import org.apache.hadoop.hbase.regionserver.HRegionServer;
+import org.apache.hadoop.hbase.regionserver.HRegion;
+import org.apache.hadoop.hbase.util.Bytes;
+import org.apache.hadoop.hbase.util.JVMClusterUtil;
+
+/**
+ * Test whether region rebalancing works. (HBASE-71)
+ * Test HBASE-3663 whether region rebalancing works after a new server booted
+ * especially when no server has more regions than the ceils of avg load
+ */
+public class TestGlobalMemStoreSize extends HBaseClusterTestCase {
+  final Log LOG = LogFactory.getLog(this.getClass().getName());
+
+  HTable table;
+
+  HTableDescriptor desc;
+
+  final byte[] FIVE_HUNDRED_KBYTES;
+
+  final byte [] FAMILY_NAME = Bytes.toBytes("col");
+
+  private static int regionServerNum =2;
+  private static int regionNum = 8;
+
+  /** constructor */
+  public TestGlobalMemStoreSize() {
+    super(regionServerNum);
+
+    FIVE_HUNDRED_KBYTES = new byte[500 * 1024];
+    for (int i = 0; i < 500 * 1024; i++) {
+      FIVE_HUNDRED_KBYTES[i] = 'x';
+    }
+
+    desc = new HTableDescriptor("test");
+    desc.addFamily(new HColumnDescriptor(FAMILY_NAME));
+  }
+
+  /**
+   * Before the hbase cluster starts up, create some dummy regions.
+   */
+  @Override
+  public void preHBaseClusterSetup() throws IOException {
+    // create a 20-region table by writing directly to disk
+    List<byte []> startKeys = new ArrayList<byte []>();
+    startKeys.add(null);
+    for (int i = 10; i < regionNum+10; i++) {
+      startKeys.add(Bytes.toBytes("row_" + i));
+    }
+    startKeys.add(null);
+    LOG.debug(startKeys.size() + " start keys generated");
+
+    List<HRegion> regions = new ArrayList<HRegion>();
+    for (int i = 0; i < regionNum; i++) {
+      regions.add(createAregion(startKeys.get(i), startKeys.get(i+1)));
+    }
+
+    // Now create the root and meta regions and insert the data regions
+    // created above into the meta
+
+    createRootAndMetaRegions();
+    for (HRegion region : regions) {
+      HRegion.addRegionToMETA(meta, region);
+    }
+    closeRootAndMeta();
+  }
+
+  /**
+   * Test the global mem store size in the region server is equal to sum of each
+   * region's mem store size
+   * @throws IOException
+   */
+
+  public void testGlobalMemStore() throws IOException {
+    waitForAllRegionsAssigned();
+    assertEquals(getOnlineRegionServers().size(), regionServerNum);
+
+    int totalRegionNum = 0;
+    for (HRegionServer server : getOnlineRegionServers()) {
+      long globalMemStoreSize = 0;
+      totalRegionNum += server.getOnlineRegions().size();
+      for(HRegion region : server.getOnlineRegions()) {
+        globalMemStoreSize += region.getMemstoreSize().get();
+      }
+      assertEquals(server.getGlobalMemstoreSize().get(),globalMemStoreSize);
+    }
+    assertEquals(totalRegionNum,regionNum);
+
+    for (HRegionServer server : getOnlineRegionServers()) {
+      for(HRegion region : server.getOnlineRegions()) {
+        region.flushcache();
+      }
+      assertEquals(server.getGlobalMemstoreSize().get(),0);
+    }
+  }
+
+  /** figure out how many regions are currently being served. */
+  private int getRegionCount() {
+    int total = 0;
+    System.out.println("getOnlineRegionServers "+ getOnlineRegionServers().size());
+    for (HRegionServer server : getOnlineRegionServers()) {
+      total += server.getOnlineRegions().size();
+    }
+    return total;
+  }
+
+  private List<HRegionServer> getOnlineRegionServers() {
+    List<HRegionServer> list = new ArrayList<HRegionServer>();
+    for (JVMClusterUtil.RegionServerThread rst : cluster.getRegionServerThreads()) {
+      if (rst.getRegionServer().isOnline()) {
+        list.add(rst.getRegionServer());
+      }
+    }
+    return list;
+  }
+
+  /**
+   * Wait until all the regions are assigned.
+   */
+  private void waitForAllRegionsAssigned() {
+    while (getRegionCount() < regionNum) {
+      LOG.debug("Waiting for there to be "+regionNum+" regions, but there are " + getRegionCount() + " right now.");
+      try {
+        Thread.sleep(1000);
+      } catch (InterruptedException e) {}
+    }
+  }
+
+  /**
+   * create a region with the specified start and end key and exactly one row
+   * inside.
+   */
+  private HRegion createAregion(byte [] startKey, byte [] endKey)
+  throws IOException {
+    HRegion region = createNewHRegion(desc, startKey, endKey);
+    byte [] keyToWrite = startKey == null ? Bytes.toBytes("row_0000") : startKey;
+    Put put = new Put(keyToWrite);
+    put.add(FAMILY_NAME, null, Bytes.toBytes("test"));
+    region.put(put);
+    region.close();
+    region.getLog().closeAndDelete();
+    return region;
+  }
+}

Modified: hbase/branches/0.89/src/test/java/org/apache/hadoop/hbase/regionserver/TestHRegion.java
URL: http://svn.apache.org/viewvc/hbase/branches/0.89/src/test/java/org/apache/hadoop/hbase/regionserver/TestHRegion.java?rev=1181507&r1=1181506&r2=1181507&view=diff
==============================================================================
--- hbase/branches/0.89/src/test/java/org/apache/hadoop/hbase/regionserver/TestHRegion.java (original)
+++ hbase/branches/0.89/src/test/java/org/apache/hadoop/hbase/regionserver/TestHRegion.java Tue Oct 11 02:14:39 2011
@@ -201,59 +201,6 @@ public class TestHRegion extends HBaseTe
     }
   }
 
-  /**
-   * A unit test to test the global mem store size during put
-   */
-  public void testGlobalMemStoreSize() throws IOException {
-    int regionNum = 3;
-    List<HRegion> regionList = new ArrayList();
-    // create multiple regions
-    for (int r = 1; r <= regionNum; r ++) {
-      byte [] tableName = Bytes.toBytes("testGlobalMemStoreSize_r"+r);
-      byte [] fam = Bytes.toBytes("fam");
-      byte [] qf  = Bytes.toBytes("col");
-      byte [] val  = Bytes.toBytes("value");
-      // Create Table
-      HColumnDescriptor hcd = new HColumnDescriptor(fam, Integer.MAX_VALUE,
-          HColumnDescriptor.DEFAULT_COMPRESSION, false, true,
-          HColumnDescriptor.DEFAULT_TTL, "rowcol");
-
-      HTableDescriptor htd = new HTableDescriptor(tableName);
-      htd.addFamily(hcd);
-      HRegionInfo info = new HRegionInfo(htd, null, null, false);
-      Path path = new Path(DIR + "testGlobalMemStoreSize_"+r);
-      HRegion region = HRegion.createHRegion(info, path, conf);
-
-      int num_unique_rows = 10;
-      int version = 0;
-
-      for (int j = 0; j < num_unique_rows; j++) {
-        Put put = new Put(Bytes.toBytes("row" + j*r));
-        put.add(fam, qf, version++, val);
-        region.put(put);
-      }
-
-      regionList.add(region);
-    }
-
-    //cal total mem size
-    long globalMemStoreSize = 0;
-    for (HRegion region : regionList) {
-      globalMemStoreSize += region.memstoreSize.get();
-    }
-    assertTrue(HRegion.getGlobalMemstoreSize() >= globalMemStoreSize);
-
-    //cal total mem size after flush
-    globalMemStoreSize = 0;
-    for (HRegion region : regionList) {
-      region.flushcache();
-      globalMemStoreSize += region.memstoreSize.get();
-    }
-
-    assertEquals(globalMemStoreSize,0L);
-    assertTrue(HRegion.getGlobalMemstoreSize() >= globalMemStoreSize);
-  }
-
   /*
    * An involved filter test.  Has multiple column families and deletes in mix.
    */