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.
*/