HDFS-8674. Improve performance of postponed block scans. Contributed by Daryn Sharp.
(cherry picked from commit 0d8a35bd6de5d2a5a9b816ca98f31975e94bd7c6) Conflicts: hadoop-hdfs-project/hadoop-hdfs/src/main/java/org/apache/hadoop/hdfs/server/blockmanagement/BlockManager.java
This commit is contained in:
parent
948d0ac72d
commit
cafee1109c
@ -114,6 +114,8 @@ Release 2.7.4 - UNRELEASED
|
|||||||
HDFS-9710. DN can be configured to send block receipt IBRs in batches.
|
HDFS-9710. DN can be configured to send block receipt IBRs in batches.
|
||||||
(Tsz-Wo Nicholas Sze. Backport HDFS-11837 by Vinitha Reddy Gankidi)
|
(Tsz-Wo Nicholas Sze. Backport HDFS-11837 by Vinitha Reddy Gankidi)
|
||||||
|
|
||||||
|
HDFS-8674. Improve performance of postponed block scans. (Daryn Sharp)
|
||||||
|
|
||||||
BUG FIXES
|
BUG FIXES
|
||||||
|
|
||||||
HDFS-8307. Spurious DNS Queries from hdfs shell. (Andres Perez via aengineer)
|
HDFS-8307. Spurious DNS Queries from hdfs shell. (Andres Perez via aengineer)
|
||||||
|
@ -27,6 +27,7 @@
|
|||||||
import java.util.EnumSet;
|
import java.util.EnumSet;
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
import java.util.Iterator;
|
import java.util.Iterator;
|
||||||
|
import java.util.LinkedHashSet;
|
||||||
import java.util.LinkedList;
|
import java.util.LinkedList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
@ -127,7 +128,6 @@ public class BlockManager {
|
|||||||
private volatile long underReplicatedBlocksCount = 0L;
|
private volatile long underReplicatedBlocksCount = 0L;
|
||||||
private volatile long scheduledReplicationBlocksCount = 0L;
|
private volatile long scheduledReplicationBlocksCount = 0L;
|
||||||
private final AtomicLong excessBlocksCount = new AtomicLong(0L);
|
private final AtomicLong excessBlocksCount = new AtomicLong(0L);
|
||||||
private final AtomicLong postponedMisreplicatedBlocksCount = new AtomicLong(0L);
|
|
||||||
private final long startupDelayBlockDeletionInMs;
|
private final long startupDelayBlockDeletionInMs;
|
||||||
|
|
||||||
/** Used by metrics */
|
/** Used by metrics */
|
||||||
@ -160,7 +160,7 @@ public long getExcessBlocksCount() {
|
|||||||
}
|
}
|
||||||
/** Used by metrics */
|
/** Used by metrics */
|
||||||
public long getPostponedMisreplicatedBlocksCount() {
|
public long getPostponedMisreplicatedBlocksCount() {
|
||||||
return postponedMisreplicatedBlocksCount.get();
|
return postponedMisreplicatedBlocks.size();
|
||||||
}
|
}
|
||||||
/** Used by metrics */
|
/** Used by metrics */
|
||||||
public int getPendingDataNodeMessageCount() {
|
public int getPendingDataNodeMessageCount() {
|
||||||
@ -196,7 +196,10 @@ public int getPendingDataNodeMessageCount() {
|
|||||||
* notified of all block deletions that might have been pending
|
* notified of all block deletions that might have been pending
|
||||||
* when the failover happened.
|
* when the failover happened.
|
||||||
*/
|
*/
|
||||||
private final Set<Block> postponedMisreplicatedBlocks = Sets.newHashSet();
|
private final LinkedHashSet<Block> postponedMisreplicatedBlocks =
|
||||||
|
new LinkedHashSet<Block>();
|
||||||
|
private final int blocksPerPostpondedRescan;
|
||||||
|
private final ArrayList<Block> rescannedMisreplicatedBlocks;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Maps a StorageID to the set of blocks that are "extra" for this
|
* Maps a StorageID to the set of blocks that are "extra" for this
|
||||||
@ -286,7 +289,10 @@ public BlockManager(final Namesystem namesystem, final Configuration conf)
|
|||||||
this.namesystem = namesystem;
|
this.namesystem = namesystem;
|
||||||
datanodeManager = new DatanodeManager(this, namesystem, conf);
|
datanodeManager = new DatanodeManager(this, namesystem, conf);
|
||||||
heartbeatManager = datanodeManager.getHeartbeatManager();
|
heartbeatManager = datanodeManager.getHeartbeatManager();
|
||||||
|
blocksPerPostpondedRescan = (int)Math.min(Integer.MAX_VALUE,
|
||||||
|
datanodeManager.getBlocksPerPostponedMisreplicatedBlocksRescan());
|
||||||
|
rescannedMisreplicatedBlocks =
|
||||||
|
new ArrayList<Block>(blocksPerPostpondedRescan);
|
||||||
startupDelayBlockDeletionInMs = conf.getLong(
|
startupDelayBlockDeletionInMs = conf.getLong(
|
||||||
DFSConfigKeys.DFS_NAMENODE_STARTUP_DELAY_BLOCK_DELETION_SEC_KEY,
|
DFSConfigKeys.DFS_NAMENODE_STARTUP_DELAY_BLOCK_DELETION_SEC_KEY,
|
||||||
DFSConfigKeys.DFS_NAMENODE_STARTUP_DELAY_BLOCK_DELETION_SEC_DEFAULT) * 1000L;
|
DFSConfigKeys.DFS_NAMENODE_STARTUP_DELAY_BLOCK_DELETION_SEC_DEFAULT) * 1000L;
|
||||||
@ -1319,9 +1325,7 @@ public void setPostponeBlocksFromFuture(boolean postpone) {
|
|||||||
|
|
||||||
|
|
||||||
private void postponeBlock(Block blk) {
|
private void postponeBlock(Block blk) {
|
||||||
if (postponedMisreplicatedBlocks.add(blk)) {
|
postponedMisreplicatedBlocks.add(blk);
|
||||||
postponedMisreplicatedBlocksCount.incrementAndGet();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -1941,39 +1945,14 @@ void rescanPostponedMisreplicatedBlocks() {
|
|||||||
if (getPostponedMisreplicatedBlocksCount() == 0) {
|
if (getPostponedMisreplicatedBlocksCount() == 0) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
long startTimeRescanPostponedMisReplicatedBlocks = Time.monotonicNow();
|
|
||||||
long startPostponedMisReplicatedBlocksCount =
|
|
||||||
getPostponedMisreplicatedBlocksCount();
|
|
||||||
namesystem.writeLock();
|
namesystem.writeLock();
|
||||||
|
long startTime = Time.monotonicNow();
|
||||||
|
long startSize = postponedMisreplicatedBlocks.size();
|
||||||
try {
|
try {
|
||||||
// blocksPerRescan is the configured number of blocks per rescan.
|
|
||||||
// Randomly select blocksPerRescan consecutive blocks from the HashSet
|
|
||||||
// when the number of blocks remaining is larger than blocksPerRescan.
|
|
||||||
// The reason we don't always pick the first blocksPerRescan blocks is to
|
|
||||||
// handle the case if for some reason some datanodes remain in
|
|
||||||
// content stale state for a long time and only impact the first
|
|
||||||
// blocksPerRescan blocks.
|
|
||||||
int i = 0;
|
|
||||||
long startIndex = 0;
|
|
||||||
long blocksPerRescan =
|
|
||||||
datanodeManager.getBlocksPerPostponedMisreplicatedBlocksRescan();
|
|
||||||
long base = getPostponedMisreplicatedBlocksCount() - blocksPerRescan;
|
|
||||||
if (base > 0) {
|
|
||||||
startIndex = DFSUtil.getRandom().nextLong() % (base+1);
|
|
||||||
if (startIndex < 0) {
|
|
||||||
startIndex += (base+1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Iterator<Block> it = postponedMisreplicatedBlocks.iterator();
|
Iterator<Block> it = postponedMisreplicatedBlocks.iterator();
|
||||||
for (int tmp = 0; tmp < startIndex; tmp++) {
|
for (int i=0; i < blocksPerPostpondedRescan && it.hasNext(); i++) {
|
||||||
it.next();
|
|
||||||
}
|
|
||||||
|
|
||||||
for (;it.hasNext(); i++) {
|
|
||||||
Block b = it.next();
|
Block b = it.next();
|
||||||
if (i >= blocksPerRescan) {
|
it.remove();
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
BlockInfoContiguous bi = blocksMap.getStoredBlock(b);
|
BlockInfoContiguous bi = blocksMap.getStoredBlock(b);
|
||||||
if (bi == null) {
|
if (bi == null) {
|
||||||
@ -1982,8 +1961,6 @@ void rescanPostponedMisreplicatedBlocks() {
|
|||||||
"Postponed mis-replicated block " + b + " no longer found " +
|
"Postponed mis-replicated block " + b + " no longer found " +
|
||||||
"in block map.");
|
"in block map.");
|
||||||
}
|
}
|
||||||
it.remove();
|
|
||||||
postponedMisreplicatedBlocksCount.decrementAndGet();
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
MisReplicationResult res = processMisReplicatedBlock(bi);
|
MisReplicationResult res = processMisReplicatedBlock(bi);
|
||||||
@ -1991,20 +1968,19 @@ void rescanPostponedMisreplicatedBlocks() {
|
|||||||
LOG.debug("BLOCK* rescanPostponedMisreplicatedBlocks: " +
|
LOG.debug("BLOCK* rescanPostponedMisreplicatedBlocks: " +
|
||||||
"Re-scanned block " + b + ", result is " + res);
|
"Re-scanned block " + b + ", result is " + res);
|
||||||
}
|
}
|
||||||
if (res != MisReplicationResult.POSTPONE) {
|
if (res == MisReplicationResult.POSTPONE) {
|
||||||
it.remove();
|
rescannedMisreplicatedBlocks.add(b);
|
||||||
postponedMisreplicatedBlocksCount.decrementAndGet();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} finally {
|
} finally {
|
||||||
|
postponedMisreplicatedBlocks.addAll(rescannedMisreplicatedBlocks);
|
||||||
|
rescannedMisreplicatedBlocks.clear();
|
||||||
|
long endSize = postponedMisreplicatedBlocks.size();
|
||||||
namesystem.writeUnlock();
|
namesystem.writeUnlock();
|
||||||
long endPostponedMisReplicatedBlocksCount =
|
|
||||||
getPostponedMisreplicatedBlocksCount();
|
|
||||||
LOG.info("Rescan of postponedMisreplicatedBlocks completed in " +
|
LOG.info("Rescan of postponedMisreplicatedBlocks completed in " +
|
||||||
(Time.monotonicNow() - startTimeRescanPostponedMisReplicatedBlocks) +
|
(Time.monotonicNow() - startTime) + " msecs. " +
|
||||||
" msecs. " + endPostponedMisReplicatedBlocksCount +
|
endSize + " blocks are left. " +
|
||||||
" blocks are left. " + (startPostponedMisReplicatedBlocksCount -
|
(startSize - endSize) + " blocks were removed.");
|
||||||
endPostponedMisReplicatedBlocksCount) + " blocks are removed.");
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -3400,9 +3376,7 @@ public void removeBlock(Block block) {
|
|||||||
// Remove the block from pendingReplications and neededReplications
|
// Remove the block from pendingReplications and neededReplications
|
||||||
pendingReplications.remove(block);
|
pendingReplications.remove(block);
|
||||||
neededReplications.remove(block, UnderReplicatedBlocks.LEVEL);
|
neededReplications.remove(block, UnderReplicatedBlocks.LEVEL);
|
||||||
if (postponedMisreplicatedBlocks.remove(block)) {
|
postponedMisreplicatedBlocks.remove(block);
|
||||||
postponedMisreplicatedBlocksCount.decrementAndGet();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public BlockInfoContiguous getStoredBlock(Block block) {
|
public BlockInfoContiguous getStoredBlock(Block block) {
|
||||||
@ -3730,7 +3704,6 @@ public void clearQueues() {
|
|||||||
invalidateBlocks.clear();
|
invalidateBlocks.clear();
|
||||||
datanodeManager.clearPendingQueues();
|
datanodeManager.clearPendingQueues();
|
||||||
postponedMisreplicatedBlocks.clear();
|
postponedMisreplicatedBlocks.clear();
|
||||||
postponedMisreplicatedBlocksCount.set(0);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user