Search in sources :

Example 1 with TabletStatistics

use of org.apache.accumulo.core.spi.balancer.data.TabletStatistics in project accumulo by apache.

the class SimpleLoadBalancer method move.

/**
 * Select a tablet based on differences between table loads; if the loads are even, use the
 * busiest table
 */
List<TabletMigration> move(ServerCounts tooMuch, ServerCounts tooLittle, int count, Map<TableId, Map<TabletId, TabletStatistics>> donerTabletStats) {
    if (count == 0) {
        return Collections.emptyList();
    }
    List<TabletMigration> result = new ArrayList<>();
    // Copy counts so we can update them as we propose migrations
    Map<TableId, Integer> tooMuchMap = tabletCountsPerTable(tooMuch.status);
    Map<TableId, Integer> tooLittleMap = tabletCountsPerTable(tooLittle.status);
    for (int i = 0; i < count; i++) {
        TableId table;
        Integer tooLittleCount;
        if (tableToBalance == null) {
            // find a table to migrate
            // look for an uneven table count
            int biggestDifference = 0;
            TableId biggestDifferenceTable = null;
            for (var tableEntry : tooMuchMap.entrySet()) {
                TableId tableID = tableEntry.getKey();
                tooLittleMap.putIfAbsent(tableID, 0);
                int diff = tableEntry.getValue() - tooLittleMap.get(tableID);
                if (diff > biggestDifference) {
                    biggestDifference = diff;
                    biggestDifferenceTable = tableID;
                }
            }
            if (biggestDifference < 2) {
                table = busiest(tooMuch.status.getTableMap());
            } else {
                table = biggestDifferenceTable;
            }
        } else {
            // just balance the given table
            table = tableToBalance;
        }
        Map<TabletId, TabletStatistics> onlineTabletsForTable = donerTabletStats.get(table);
        try {
            if (onlineTabletsForTable == null) {
                onlineTabletsForTable = new HashMap<>();
                List<TabletStatistics> stats = getOnlineTabletsForTable(tooMuch.server, table);
                if (stats == null) {
                    log.warn("Unable to find tablets to move");
                    return result;
                }
                for (TabletStatistics stat : stats) onlineTabletsForTable.put(stat.getTabletId(), stat);
                donerTabletStats.put(table, onlineTabletsForTable);
            }
        } catch (Exception ex) {
            log.error("Unable to select a tablet to move", ex);
            return result;
        }
        TabletId tabletId = selectTablet(onlineTabletsForTable);
        onlineTabletsForTable.remove(tabletId);
        if (tabletId == null)
            return result;
        tooMuchMap.put(table, tooMuchMap.get(table) - 1);
        /*
       * If a table grows from 1 tablet then tooLittleMap.get(table) can return a null, since there
       * is only one tabletserver that holds all of the tablets. Here we check to see if in fact
       * that is the case and if so set the value to 0.
       */
        tooLittleCount = tooLittleMap.get(table);
        if (tooLittleCount == null) {
            tooLittleCount = 0;
        }
        tooLittleMap.put(table, tooLittleCount + 1);
        tooMuch.count--;
        tooLittle.count++;
        result.add(new TabletMigration(tabletId, tooMuch.server, tooLittle.server));
    }
    return result;
}
Also used : TableId(org.apache.accumulo.core.data.TableId) TabletMigration(org.apache.accumulo.core.spi.balancer.data.TabletMigration) ArrayList(java.util.ArrayList) AccumuloSecurityException(org.apache.accumulo.core.client.AccumuloSecurityException) AccumuloException(org.apache.accumulo.core.client.AccumuloException) TabletId(org.apache.accumulo.core.data.TabletId) TabletStatistics(org.apache.accumulo.core.spi.balancer.data.TabletStatistics)

Example 2 with TabletStatistics

use of org.apache.accumulo.core.spi.balancer.data.TabletStatistics in project accumulo by apache.

the class SimpleLoadBalancer method selectTablet.

static TabletId selectTablet(Map<TabletId, TabletStatistics> extents) {
    if (extents.isEmpty())
        return null;
    TabletId mostRecentlySplit = null;
    long splitTime = 0;
    for (Entry<TabletId, TabletStatistics> entry : extents.entrySet()) if (entry.getValue().getSplitCreationTime() >= splitTime) {
        splitTime = entry.getValue().getSplitCreationTime();
        mostRecentlySplit = entry.getKey();
    }
    return mostRecentlySplit;
}
Also used : TabletId(org.apache.accumulo.core.data.TabletId) TabletStatistics(org.apache.accumulo.core.spi.balancer.data.TabletStatistics)

Example 3 with TabletStatistics

use of org.apache.accumulo.core.spi.balancer.data.TabletStatistics in project accumulo by apache.

the class ChaoticLoadBalancer method balance.

@Override
public long balance(BalanceParameters params) {
    Map<TabletServerId, Long> numTablets = new HashMap<>();
    List<TabletServerId> underCapacityTServer = new ArrayList<>();
    if (!params.currentMigrations().isEmpty()) {
        outstandingMigrationsProblem.setMigrations(params.currentMigrations());
        problemReporter.reportProblem(outstandingMigrationsProblem);
        return 100;
    }
    problemReporter.clearProblemReportTimes();
    boolean moveMetadata = random.nextInt(4) == 0;
    long totalTablets = 0;
    for (Entry<TabletServerId, TServerStatus> e : params.currentStatus().entrySet()) {
        long tabletCount = 0;
        for (TableStatistics ti : e.getValue().getTableMap().values()) {
            tabletCount += ti.getTabletCount();
        }
        numTablets.put(e.getKey(), tabletCount);
        underCapacityTServer.add(e.getKey());
        totalTablets += tabletCount;
    }
    // totalTablets is fuzzy due to asynchronicity of the stats
    // *1.2 to handle fuzziness, and prevent locking for 'perfect' balancing scenarios
    long avg = (long) Math.ceil(((double) totalTablets) / params.currentStatus().size() * 1.2);
    for (Entry<TabletServerId, TServerStatus> e : params.currentStatus().entrySet()) {
        for (String tableId : e.getValue().getTableMap().keySet()) {
            TableId id = TableId.of(tableId);
            if (!moveMetadata && MetadataTable.ID.equals(id))
                continue;
            try {
                for (TabletStatistics ts : getOnlineTabletsForTable(e.getKey(), id)) {
                    int index = random.nextInt(underCapacityTServer.size());
                    TabletServerId dest = underCapacityTServer.get(index);
                    if (dest.equals(e.getKey()))
                        continue;
                    params.migrationsOut().add(new TabletMigration(ts.getTabletId(), e.getKey(), dest));
                    if (numTablets.put(dest, numTablets.get(dest) + 1) > avg)
                        underCapacityTServer.remove(index);
                    if (numTablets.put(e.getKey(), numTablets.get(e.getKey()) - 1) <= avg && !underCapacityTServer.contains(e.getKey()))
                        underCapacityTServer.add(e.getKey());
                    // option!
                    if (underCapacityTServer.isEmpty())
                        underCapacityTServer.addAll(numTablets.keySet());
                }
            } catch (AccumuloSecurityException e1) {
                // Shouldn't happen, but carry on if it does
                log.debug("Encountered AccumuloSecurityException.  This should not happen.  Carrying on anyway.", e1);
            } catch (AccumuloException e1) {
                // Shouldn't happen, but carry on if it does
                log.debug("Encountered AccumuloException.  This should not happen.  Carrying on anyway.", e1);
            }
        }
    }
    return 100;
}
Also used : TableId(org.apache.accumulo.core.data.TableId) AccumuloException(org.apache.accumulo.core.client.AccumuloException) TabletMigration(org.apache.accumulo.core.spi.balancer.data.TabletMigration) HashMap(java.util.HashMap) ArrayList(java.util.ArrayList) TServerStatus(org.apache.accumulo.core.spi.balancer.data.TServerStatus) TabletServerId(org.apache.accumulo.core.spi.balancer.data.TabletServerId) TableStatistics(org.apache.accumulo.core.spi.balancer.data.TableStatistics) TabletStatistics(org.apache.accumulo.core.spi.balancer.data.TabletStatistics) AccumuloSecurityException(org.apache.accumulo.core.client.AccumuloSecurityException)

Example 4 with TabletStatistics

use of org.apache.accumulo.core.spi.balancer.data.TabletStatistics in project accumulo by apache.

the class HostRegexTableLoadBalancer method balance.

@Override
public long balance(BalanceParameters params) {
    long minBalanceTime = 20_000;
    // Iterate over the tables and balance each of them
    Map<String, TableId> tableIdMap = environment.getTableIdMap();
    Map<TableId, String> tableIdToTableName = tableIdMap.entrySet().stream().collect(Collectors.toMap(Map.Entry::getValue, Map.Entry::getKey));
    tableIdToTableName.keySet().forEach(this::checkTableConfig);
    long now = System.currentTimeMillis();
    HrtlbConf myConf = hrtlbConf.get();
    SortedMap<TabletServerId, TServerStatus> current = params.currentStatus();
    Set<TabletId> migrations = params.currentMigrations();
    List<TabletMigration> migrationsOut = params.migrationsOut();
    Map<String, SortedMap<TabletServerId, TServerStatus>> currentGrouped = splitCurrentByRegex(params.currentStatus());
    if ((now - this.lastOOBCheck) > myConf.oobCheckMillis) {
        try {
            // Check to see if a tablet is assigned outside the bounds of the pool. If so, migrate it.
            for (String table : tableIdMap.keySet()) {
                LOG.debug("Checking for out of bounds tablets for table {}", table);
                String tablePoolName = getPoolNameForTable(table);
                for (Entry<TabletServerId, TServerStatus> 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());
                    if (hostPools.contains(tablePoolName)) {
                        continue;
                    }
                    TableId tid = tableIdMap.get(table);
                    if (tid == null) {
                        LOG.warn("Unable to check for out of bounds tablets for table {}," + " it may have been deleted or renamed.", table);
                        continue;
                    }
                    try {
                        List<TabletStatistics> outOfBoundsTablets = getOnlineTabletsForTable(e.getKey(), tid);
                        if (outOfBoundsTablets == null) {
                            continue;
                        }
                        for (TabletStatistics ts : outOfBoundsTablets) {
                            if (migrations.contains(ts.getTabletId())) {
                                LOG.debug("Migration for out of bounds tablet {} has already been requested", ts.getTabletId());
                                continue;
                            }
                            String poolName = getPoolNameForTable(table);
                            SortedMap<TabletServerId, TServerStatus> currentView = currentGrouped.get(poolName);
                            if (currentView != null) {
                                int skip = random.nextInt(currentView.size());
                                Iterator<TabletServerId> iter = currentView.keySet().iterator();
                                for (int i = 0; i < skip; i++) {
                                    iter.next();
                                }
                                TabletServerId nextTS = iter.next();
                                LOG.info("Tablet {} is currently outside the bounds of the" + " regex, migrating from {} to {}", ts.getTabletId(), e.getKey(), nextTS);
                                migrationsOut.add(new TabletMigration(ts.getTabletId(), e.getKey(), nextTS));
                                if (migrationsOut.size() >= myConf.maxTServerMigrations) {
                                    break;
                                }
                            } else {
                                LOG.warn("No tablet servers online for pool {}, unable to" + " migrate out of bounds tablets", poolName);
                            }
                        }
                    } catch (AccumuloException | AccumuloSecurityException e1) {
                        LOG.error("Error in OOB check getting tablets for table {} from server {} {}", tid, e.getKey().getHost(), e);
                    }
                }
            }
        } finally {
            // this could have taken a while...get a new time
            this.lastOOBCheck = System.currentTimeMillis();
        }
    }
    if (!migrationsOut.isEmpty()) {
        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.isEmpty()) {
        if (migrations.size() >= myConf.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<TabletServerId, TServerStatusImpl> currentCopy = new TreeMap<>();
        current.forEach((tid, status) -> currentCopy.put(tid, (TServerStatusImpl) status));
        Multimap<TabletServerId, String> serverTableIdCopied = HashMultimap.create();
        for (TabletMigration migration : migrationsFromLastPass.values()) {
            TableStatisticsImpl fromInfo = getTableInfo(currentCopy, serverTableIdCopied, migration.getTablet().getTable().canonical(), migration.getOldTabletServer());
            if (fromInfo != null) {
                fromInfo.setOnlineTabletCount(fromInfo.getOnlineTabletCount() - 1);
            }
            TableStatisticsImpl toInfo = getTableInfo(currentCopy, serverTableIdCopied, migration.getTablet().getTable().canonical(), migration.getNewTabletServer());
            if (toInfo != null) {
                toInfo.setOnlineTabletCount(toInfo.getOnlineTabletCount() + 1);
            }
        }
        migrations = EMPTY_MIGRATIONS;
    } else {
        migrationsFromLastPass.clear();
    }
    for (TableId tableId : tableIdMap.values()) {
        String tableName = tableIdToTableName.get(tableId);
        String regexTableName = getPoolNameForTable(tableName);
        SortedMap<TabletServerId, TServerStatus> currentView = currentGrouped.get(regexTableName);
        if (currentView == null) {
            LOG.warn("Skipping balance for table {} as no tablet servers are online.", tableName);
            continue;
        }
        ArrayList<TabletMigration> newMigrations = new ArrayList<>();
        getBalancerForTable(tableId).balance(new BalanceParamsImpl(currentView, migrations, newMigrations));
        if (newMigrations.isEmpty()) {
            tableToTimeSinceNoMigrations.remove(tableId);
        } else if (tableToTimeSinceNoMigrations.containsKey(tableId)) {
            if ((now - tableToTimeSinceNoMigrations.get(tableId)) > HOURS.toMillis(1)) {
                LOG.warn("We have been consistently producing migrations for {}: {}", tableName, Iterables.limit(newMigrations, 10));
            }
        } else {
            tableToTimeSinceNoMigrations.put(tableId, now);
        }
        migrationsOut.addAll(newMigrations);
        if (migrationsOut.size() >= myConf.maxTServerMigrations) {
            break;
        }
    }
    for (TabletMigration migration : migrationsOut) {
        migrationsFromLastPass.put(migration.getTablet(), migration);
    }
    LOG.info("Migrating tablets for balance: {}", migrationsOut);
    return minBalanceTime;
}
Also used : TableId(org.apache.accumulo.core.data.TableId) ArrayList(java.util.ArrayList) TServerStatusImpl(org.apache.accumulo.core.manager.balancer.TServerStatusImpl) TabletServerId(org.apache.accumulo.core.spi.balancer.data.TabletServerId) TabletStatistics(org.apache.accumulo.core.spi.balancer.data.TabletStatistics) AccumuloSecurityException(org.apache.accumulo.core.client.AccumuloSecurityException) AccumuloException(org.apache.accumulo.core.client.AccumuloException) BalanceParamsImpl(org.apache.accumulo.core.manager.balancer.BalanceParamsImpl) TabletMigration(org.apache.accumulo.core.spi.balancer.data.TabletMigration) TServerStatus(org.apache.accumulo.core.spi.balancer.data.TServerStatus) TreeMap(java.util.TreeMap) TableStatisticsImpl(org.apache.accumulo.core.manager.balancer.TableStatisticsImpl) SortedMap(java.util.SortedMap) TabletId(org.apache.accumulo.core.data.TabletId) HashMap(java.util.HashMap) Map(java.util.Map) TreeMap(java.util.TreeMap) SortedMap(java.util.SortedMap)

Example 5 with TabletStatistics

use of org.apache.accumulo.core.spi.balancer.data.TabletStatistics in project accumulo by apache.

the class HostRegexTableLoadBalancerReconfigurationTest method getOnlineTabletsForTable.

@Override
public List<TabletStatistics> getOnlineTabletsForTable(TabletServerId tserver, TableId tableId) {
    List<TabletStatistics> tablets = new ArrayList<>();
    // Report assignment information
    for (Entry<TabletId, TabletServerId> e : this.assignments.entrySet()) {
        if (e.getValue().equals(tserver) && e.getKey().getTable().equals(tableId)) {
            TabletStats ts = new TabletStats();
            TabletId tid = e.getKey();
            ts.setExtent(new KeyExtent(tid.getTable(), tid.getEndRow(), tid.getPrevEndRow()).toThrift());
            tablets.add(new TabletStatisticsImpl(ts));
        }
    }
    return tablets;
}
Also used : TabletServerId(org.apache.accumulo.core.spi.balancer.data.TabletServerId) TabletStats(org.apache.accumulo.core.tabletserver.thrift.TabletStats) ArrayList(java.util.ArrayList) TabletStatistics(org.apache.accumulo.core.spi.balancer.data.TabletStatistics) TabletId(org.apache.accumulo.core.data.TabletId) KeyExtent(org.apache.accumulo.core.dataImpl.KeyExtent) TabletStatisticsImpl(org.apache.accumulo.core.manager.balancer.TabletStatisticsImpl)

Aggregations

TabletStatistics (org.apache.accumulo.core.spi.balancer.data.TabletStatistics)7 ArrayList (java.util.ArrayList)6 TabletId (org.apache.accumulo.core.data.TabletId)4 AccumuloException (org.apache.accumulo.core.client.AccumuloException)3 AccumuloSecurityException (org.apache.accumulo.core.client.AccumuloSecurityException)3 TableId (org.apache.accumulo.core.data.TableId)3 TabletStatisticsImpl (org.apache.accumulo.core.manager.balancer.TabletStatisticsImpl)3 TServerStatus (org.apache.accumulo.core.spi.balancer.data.TServerStatus)3 TabletMigration (org.apache.accumulo.core.spi.balancer.data.TabletMigration)3 TabletServerId (org.apache.accumulo.core.spi.balancer.data.TabletServerId)3 TabletStats (org.apache.accumulo.core.tabletserver.thrift.TabletStats)3 HashMap (java.util.HashMap)2 KeyExtent (org.apache.accumulo.core.dataImpl.KeyExtent)2 Map (java.util.Map)1 SortedMap (java.util.SortedMap)1 TreeMap (java.util.TreeMap)1 TKeyExtent (org.apache.accumulo.core.dataImpl.thrift.TKeyExtent)1 BalanceParamsImpl (org.apache.accumulo.core.manager.balancer.BalanceParamsImpl)1 TServerStatusImpl (org.apache.accumulo.core.manager.balancer.TServerStatusImpl)1 TableStatisticsImpl (org.apache.accumulo.core.manager.balancer.TableStatisticsImpl)1