use of org.apache.accumulo.server.master.state.TabletMigration in project accumulo by apache.
the class GroupBalancer method populateMigrations.
private void populateMigrations(Set<TServerInstance> current, List<TabletMigration> migrationsOut, Moves moves) {
if (moves.size() == 0) {
return;
}
Function<KeyExtent, String> partitioner = getPartitioner();
for (Pair<KeyExtent, Location> entry : getLocationProvider()) {
String group = partitioner.apply(entry.getFirst());
Location loc = entry.getSecond();
if (loc.equals(Location.NONE) || !current.contains(loc.getTserverInstance())) {
migrationsOut.clear();
return;
}
TServerInstance dest = moves.removeMove(loc.getTserverInstance(), group);
if (dest != null) {
migrationsOut.add(new TabletMigration(entry.getFirst(), loc.getTserverInstance(), dest));
if (moves.size() == 0) {
break;
}
}
}
}
use of org.apache.accumulo.server.master.state.TabletMigration in project accumulo by apache.
the class TableLoadBalancer method balance.
@Override
public long balance(SortedMap<TServerInstance, TabletServerStatus> current, Set<KeyExtent> migrations, List<TabletMigration> migrationsOut) {
long minBalanceTime = 5 * 1000;
// Iterate over the tables and balance each of them
TableOperations t = getTableOperations();
if (t == null)
return minBalanceTime;
for (String s : t.tableIdMap().values()) {
ArrayList<TabletMigration> newMigrations = new ArrayList<>();
long tableBalanceTime = getBalancerForTable(Table.ID.of(s)).balance(current, migrations, newMigrations);
if (tableBalanceTime < minBalanceTime)
minBalanceTime = tableBalanceTime;
migrationsOut.addAll(newMigrations);
}
return minBalanceTime;
}
use of org.apache.accumulo.server.master.state.TabletMigration in project accumulo by apache.
the class HostRegexTableLoadBalancer method balance.
@Override
public long balance(SortedMap<TServerInstance, TabletServerStatus> current, Set<KeyExtent> migrations, List<TabletMigration> migrationsOut) {
long minBalanceTime = 20 * 1000;
// Iterate over the tables and balance each of them
TableOperations t = getTableOperations();
if (t == null)
return minBalanceTime;
Map<String, String> tableIdMap = t.tableIdMap();
long now = System.currentTimeMillis();
Map<String, SortedMap<TServerInstance, TabletServerStatus>> currentGrouped = splitCurrentByRegex(current);
if ((now - this.lastOOBCheck) > this.oobCheckMillis) {
try {
// Check to see if a tablet is assigned outside the bounds of the pool. If so, migrate it.
for (String table : t.list()) {
LOG.debug("Checking for out of bounds tablets for table {}", table);
String tablePoolName = getPoolNameForTable(table);
for (Entry<TServerInstance, TabletServerStatus> e : current.entrySet()) {
// pool names are the same as table names, except in the DEFAULT case.
// If this table is assigned to a pool for this host, then move on.
List<String> hostPools = getPoolNamesForHost(e.getKey().host());
if (hostPools.contains(tablePoolName)) {
continue;
}
String tid = tableIdMap.get(table);
if (null == tid) {
LOG.warn("Unable to check for out of bounds tablets for table {}, it may have been deleted or renamed.", table);
continue;
}
try {
List<TabletStats> outOfBoundsTablets = getOnlineTabletsForTable(e.getKey(), Table.ID.of(tid));
if (null == outOfBoundsTablets) {
continue;
}
Random random = new Random();
for (TabletStats ts : outOfBoundsTablets) {
KeyExtent ke = new KeyExtent(ts.getExtent());
if (migrations.contains(ke)) {
LOG.debug("Migration for out of bounds tablet {} has already been requested", ke);
continue;
}
String poolName = getPoolNameForTable(table);
SortedMap<TServerInstance, TabletServerStatus> currentView = currentGrouped.get(poolName);
if (null != currentView) {
int skip = random.nextInt(currentView.size());
Iterator<TServerInstance> iter = currentView.keySet().iterator();
for (int i = 0; i < skip; i++) {
iter.next();
}
TServerInstance nextTS = iter.next();
LOG.info("Tablet {} is currently outside the bounds of the regex, migrating from {} to {}", ke, e.getKey(), nextTS);
migrationsOut.add(new TabletMigration(ke, e.getKey(), nextTS));
if (migrationsOut.size() >= this.maxTServerMigrations) {
break;
}
} else {
LOG.warn("No tablet servers online for pool {}, unable to migrate out of bounds tablets", poolName);
}
}
} catch (TException e1) {
LOG.error("Error in OOB check getting tablets for table {} from server {}", tid, e.getKey().host(), e);
}
}
}
} finally {
// this could have taken a while...get a new time
this.lastOOBCheck = System.currentTimeMillis();
}
}
if (migrationsOut.size() > 0) {
LOG.warn("Not balancing tables due to moving {} out of bounds tablets", migrationsOut.size());
LOG.info("Migrating out of bounds tablets: {}", migrationsOut);
return minBalanceTime;
}
if (migrations != null && migrations.size() > 0) {
if (migrations.size() >= maxOutstandingMigrations) {
LOG.warn("Not balancing tables due to {} outstanding migrations", migrations.size());
if (LOG.isTraceEnabled()) {
LOG.trace("Sample up to 10 outstanding migrations: {}", Iterables.limit(migrations, 10));
}
return minBalanceTime;
}
LOG.debug("Current outstanding migrations of {} being applied", migrations.size());
if (LOG.isTraceEnabled()) {
LOG.trace("Sample up to 10 outstanding migrations: {}", Iterables.limit(migrations, 10));
}
migrationsFromLastPass.keySet().retainAll(migrations);
SortedMap<TServerInstance, TabletServerStatus> currentCopy = new TreeMap<>(current);
Multimap<TServerInstance, String> serverTableIdCopied = HashMultimap.create();
for (TabletMigration migration : migrationsFromLastPass.values()) {
TableInfo fromInfo = getTableInfo(currentCopy, serverTableIdCopied, migration.tablet.getTableId().toString(), migration.oldServer);
if (fromInfo != null) {
fromInfo.setOnlineTablets(fromInfo.getOnlineTablets() - 1);
}
TableInfo toInfo = getTableInfo(currentCopy, serverTableIdCopied, migration.tablet.getTableId().toString(), migration.newServer);
if (toInfo != null) {
toInfo.setOnlineTablets(toInfo.getOnlineTablets() + 1);
}
}
migrations = EMPTY_MIGRATIONS;
} else {
migrationsFromLastPass.clear();
}
for (String s : tableIdMap.values()) {
Table.ID tableId = Table.ID.of(s);
String tableName = tableIdToTableName.get(tableId);
String regexTableName = getPoolNameForTable(tableName);
SortedMap<TServerInstance, TabletServerStatus> currentView = currentGrouped.get(regexTableName);
if (null == currentView) {
LOG.warn("Skipping balance for table {} as no tablet servers are online.", tableName);
continue;
}
ArrayList<TabletMigration> newMigrations = new ArrayList<>();
getBalancerForTable(tableId).balance(currentView, migrations, newMigrations);
if (newMigrations.isEmpty()) {
tableToTimeSinceNoMigrations.remove(s);
} else if (tableToTimeSinceNoMigrations.containsKey(s)) {
if ((now - tableToTimeSinceNoMigrations.get(s)) > ONE_HOUR) {
LOG.warn("We have been consistently producing migrations for {}: {}", tableName, Iterables.limit(newMigrations, 10));
}
} else {
tableToTimeSinceNoMigrations.put(s, now);
}
migrationsOut.addAll(newMigrations);
if (migrationsOut.size() >= this.maxTServerMigrations) {
break;
}
}
for (TabletMigration migration : migrationsOut) {
migrationsFromLastPass.put(migration.tablet, migration);
}
LOG.info("Migrating tablets for balance: {}", migrationsOut);
return minBalanceTime;
}
use of org.apache.accumulo.server.master.state.TabletMigration in project accumulo by apache.
the class DefaultLoadBalancerTest method testUnevenAssignment2.
@Test
public void testUnevenAssignment2() {
// make 26 servers
for (char c : "abcdefghijklmnopqrstuvwxyz".toCharArray()) {
String cString = Character.toString(c);
HostAndPort fakeAddress = HostAndPort.fromParts("127.0.0.1", c);
String fakeInstance = cString;
TServerInstance tsi = new TServerInstance(fakeAddress, fakeInstance);
FakeTServer fakeTServer = new FakeTServer();
servers.put(tsi, fakeTServer);
}
// put 60 tablets on 25 of them
List<Entry<TServerInstance, FakeTServer>> shortList = new ArrayList<>(servers.entrySet());
Entry<TServerInstance, FakeTServer> shortServer = shortList.remove(0);
int c = 0;
for (int i = 0; i < 60; i++) {
for (Entry<TServerInstance, FakeTServer> entry : shortList) {
entry.getValue().extents.add(makeExtent("t" + c, null, null));
}
}
// put 10 on the that short server:
for (int i = 0; i < 10; i++) {
shortServer.getValue().extents.add(makeExtent("s" + i, null, null));
}
TestDefaultLoadBalancer balancer = new TestDefaultLoadBalancer();
Set<KeyExtent> migrations = Collections.emptySet();
int moved = 0;
// balance until we can't balance no more!
while (true) {
List<TabletMigration> migrationsOut = new ArrayList<>();
balancer.balance(getAssignments(servers), migrations, migrationsOut);
if (migrationsOut.size() == 0)
break;
for (TabletMigration migration : migrationsOut) {
if (servers.get(migration.oldServer).extents.remove(migration.tablet))
moved++;
last.remove(migration.tablet);
servers.get(migration.newServer).extents.add(migration.tablet);
last.put(migration.tablet, migration.newServer);
}
}
// average is 58, with 2 at 59: we need 48 more moved to the short server
assertEquals(48, moved);
}
use of org.apache.accumulo.server.master.state.TabletMigration in project accumulo by apache.
the class HostRegexTableLoadBalancerTest method testBalanceWithTooManyOutstandingMigrations.
@Test
public void testBalanceWithTooManyOutstandingMigrations() {
List<TabletMigration> migrationsOut = new ArrayList<>();
init(new AccumuloServerContext(instance, factory));
// lets say we already have migrations ongoing for the FOO and BAR table extends (should be 5 of each of them) for a total of 10
Set<KeyExtent> migrations = new HashSet<>();
migrations.addAll(tableExtents.get(FOO.getTableName()));
migrations.addAll(tableExtents.get(BAR.getTableName()));
long wait = this.balance(Collections.unmodifiableSortedMap(createCurrent(15)), migrations, migrationsOut);
Assert.assertEquals(20000, wait);
// no migrations should have occurred as 10 is the maxOutstandingMigrations
Assert.assertEquals(0, migrationsOut.size());
}
Aggregations