You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@bookkeeper.apache.org by ay...@apache.org on 2022/03/10 00:04:25 UTC

[bookkeeper] branch master updated: Add throttle for rebuild entryMetadataMap

This is an automated email from the ASF dual-hosted git repository.

ayegorov pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/bookkeeper.git


The following commit(s) were added to refs/heads/master by this push:
     new 181a6dc  Add throttle for rebuild entryMetadataMap
181a6dc is described below

commit 181a6dcd35485613d65fdf2bad082bc1ef97f313
Author: Hang Chen <ch...@apache.org>
AuthorDate: Thu Mar 10 08:04:20 2022 +0800

    Add throttle for rebuild entryMetadataMap
    
    ### Motivation
    When a bookie restart, the garbageCollectorThread will rebuild entryMetadataMap from all the entry log files in ledger directory. For normal case, it will extract the EntryLogMetadata from the index in entry log file. However, if there's no index, then fallback to scanning the entry log file.
    
    In user's production environment, the log files without index occupied 4%. The total entry log files is 80000, and the log files without index is 3000. The default entry log file size is 2GB, and the garbageCollectorThread will read 3000 * 2GB = 6TB data without speed limit, which will cause ledger disk IO util runs high for dozens of minutes and affect ledger read and write latency.
    
    ### Modification
    1. Add read speed rate limiter for scanning entry log file in entryMetadataMap rebuild.
    
    Reviewers: Nicolò Boschi <bo...@gmail.com>, Enrico Olivelli <eo...@gmail.com>
    
    This closes #2963 from hangc0276/chenhang/add_throttle_for_build_entryMetadataMap
---
 .../org/apache/bookkeeper/bookie/EntryLogger.java  | 25 +++++++++++++++++++++-
 .../bookkeeper/bookie/GarbageCollectorThread.java  |  4 +++-
 2 files changed, 27 insertions(+), 2 deletions(-)

diff --git a/bookkeeper-server/src/main/java/org/apache/bookkeeper/bookie/EntryLogger.java b/bookkeeper-server/src/main/java/org/apache/bookkeeper/bookie/EntryLogger.java
index 49a9ca4..8be995a 100644
--- a/bookkeeper-server/src/main/java/org/apache/bookkeeper/bookie/EntryLogger.java
+++ b/bookkeeper-server/src/main/java/org/apache/bookkeeper/bookie/EntryLogger.java
@@ -1055,7 +1055,7 @@ public class EntryLogger {
     }
 
     public EntryLogMetadata getEntryLogMetadata(long entryLogId) throws IOException {
-        // First try to extract the EntryLogMetada from the index, if there's no index then fallback to scanning the
+        // First try to extract the EntryLogMetadata from the index, if there's no index then fallback to scanning the
         // entry log
         try {
             return extractEntryLogMetadataFromIndex(entryLogId);
@@ -1067,6 +1067,20 @@ public class EntryLogger {
         }
     }
 
+    public EntryLogMetadata getEntryLogMetadata(long entryLogId, AbstractLogCompactor.Throttler throttler)
+        throws IOException {
+        // First try to extract the EntryLogMetadata from the index, if there's no index then fallback to scanning the
+        // entry log
+        try {
+            return extractEntryLogMetadataFromIndex(entryLogId);
+        } catch (Exception e) {
+            LOG.info("Failed to get ledgers map index from: {}.log : {}", entryLogId, e.getMessage());
+
+            // Fall-back to scanning
+            return extractEntryLogMetadataByScanning(entryLogId, throttler);
+        }
+    }
+
     EntryLogMetadata extractEntryLogMetadataFromIndex(long entryLogId) throws IOException {
         Header header = getHeaderForLogId(entryLogId);
 
@@ -1151,12 +1165,21 @@ public class EntryLogger {
     }
 
     private EntryLogMetadata extractEntryLogMetadataByScanning(long entryLogId) throws IOException {
+        return extractEntryLogMetadataByScanning(entryLogId, null);
+    }
+
+    private EntryLogMetadata extractEntryLogMetadataByScanning(long entryLogId,
+                                                               AbstractLogCompactor.Throttler throttler)
+        throws IOException {
         final EntryLogMetadata meta = new EntryLogMetadata(entryLogId);
 
         // Read through the entry log file and extract the entry log meta
         scanEntryLog(entryLogId, new EntryLogScanner() {
             @Override
             public void process(long ledgerId, long offset, ByteBuf entry) throws IOException {
+                if (throttler != null) {
+                    throttler.acquire(conf.getIsThrottleByBytes() ? entry.readableBytes() : 1);
+                }
                 // add new entry size of a ledger to entry log meta
                 meta.addLedgerSize(ledgerId, entry.readableBytes() + 4);
             }
diff --git a/bookkeeper-server/src/main/java/org/apache/bookkeeper/bookie/GarbageCollectorThread.java b/bookkeeper-server/src/main/java/org/apache/bookkeeper/bookie/GarbageCollectorThread.java
index 6b559e0..6195169 100644
--- a/bookkeeper-server/src/main/java/org/apache/bookkeeper/bookie/GarbageCollectorThread.java
+++ b/bookkeeper-server/src/main/java/org/apache/bookkeeper/bookie/GarbageCollectorThread.java
@@ -126,6 +126,7 @@ public class GarbageCollectorThread extends SafeRunnable {
     final LedgerDirsManager ledgerDirsManager;
 
     private static final AtomicLong threadNum = new AtomicLong(0);
+    final AbstractLogCompactor.Throttler throttler;
     /**
      * Create a garbage collector thread.
      *
@@ -216,6 +217,7 @@ public class GarbageCollectorThread extends SafeRunnable {
             this.compactor = new EntryLogCompactor(conf, entryLogger, ledgerStorage, remover);
         }
 
+        this.throttler = new AbstractLogCompactor.Throttler(conf);
         if (minorCompactionInterval > 0 && minorCompactionThreshold > 0) {
             if (minorCompactionThreshold > 1.0f) {
                 throw new IOException("Invalid minor compaction threshold "
@@ -696,7 +698,7 @@ public class GarbageCollectorThread extends SafeRunnable {
 
             try {
                 // Read through the entry log file and extract the entry log meta
-                EntryLogMetadata entryLogMeta = entryLogger.getEntryLogMetadata(entryLogId);
+                EntryLogMetadata entryLogMeta = entryLogger.getEntryLogMetadata(entryLogId, throttler);
                 removeIfLedgerNotExists(entryLogMeta);
                 if (entryLogMeta.isEmpty()) {
                     entryLogger.removeEntryLog(entryLogId);