This is an automated email from the ASF dual-hosted git repository.
yong 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 48a87a8 Support multi ledger directories for rocksdb backend
entryMetadataMap (#2965)
48a87a8 is described below
commit 48a87a88f7d98fb890ed2aef58487f19f32a8296
Author: Hang Chen <[email protected]>
AuthorDate: Fri Feb 11 11:12:27 2022 +0800
Support multi ledger directories for rocksdb backend entryMetadataMap
(#2965)
### Motivation
When we use RocksDB backend entryMetadataMap for multi ledger directories
configured, the bookie start up failed, and throw the following exception.
```
12:24:28.530 [main] ERROR org.apache.pulsar.PulsarStandaloneStarter -
Failed to start pulsar service.
java.io.IOException: Error open RocksDB database
at
org.apache.bookkeeper.bookie.storage.ldb.KeyValueStorageRocksDB.<init>(KeyValueStorageRocksDB.java:202)
~[org.apache.bookkeeper-bookkeeper-server-4.15.0-SNAPSHOT.jar:4.15.0-SNAPSHOT]
at
org.apache.bookkeeper.bookie.storage.ldb.KeyValueStorageRocksDB.<init>(KeyValueStorageRocksDB.java:89)
~[org.apache.bookkeeper-bookkeeper-server-4.15.0-SNAPSHOT.jar:4.15.0-SNAPSHOT]
at
org.apache.bookkeeper.bookie.storage.ldb.KeyValueStorageRocksDB.lambda$static$0(KeyValueStorageRocksDB.java:62)
~[org.apache.bookkeeper-bookkeeper-server-4.15.0-SNAPSHOT.jar:4.15.0-SNAPSHOT]
at
org.apache.bookkeeper.bookie.storage.ldb.PersistentEntryLogMetadataMap.<init>(PersistentEntryLogMetadataMap.java:87)
~[org.apache.bookkeeper-bookkeeper-server-4.15.0-SNAPSHOT.jar:4.15.0-SNAPSHOT]
at
org.apache.bookkeeper.bookie.GarbageCollectorThread.createEntryLogMetadataMap(GarbageCollectorThread.java:265)
~[org.apache.bookkeeper-bookkeeper-server-4.15.0-SNAPSHOT.jar:4.15.0-SNAPSHOT]
at
org.apache.bookkeeper.bookie.GarbageCollectorThread.<init>(GarbageCollectorThread.java:154)
~[org.apache.bookkeeper-bookkeeper-server-4.15.0-SNAPSHOT.jar:4.15.0-SNAPSHOT]
at
org.apache.bookkeeper.bookie.GarbageCollectorThread.<init>(GarbageCollectorThread.java:133)
~[org.apache.bookkeeper-bookkeeper-server-4.15.0-SNAPSHOT.jar:4.15.0-SNAPSHOT]
at
org.apache.bookkeeper.bookie.storage.ldb.SingleDirectoryDbLedgerStorage.<init>(SingleDirectoryDbLedgerStorage.java:182)
~[org.apache.bookkeeper-bookkeeper-server-4.15.0-SNAPSHOT.jar:4.15.0-SNAPSHOT]
at
org.apache.bookkeeper.bookie.storage.ldb.DbLedgerStorage.newSingleDirectoryDbLedgerStorage(DbLedgerStorage.java:190)
~[org.apache.bookkeeper-bookkeeper-server-4.15.0-SNAPSHOT.jar:4.15.0-SNAPSHOT]
at
org.apache.bookkeeper.bookie.storage.ldb.DbLedgerStorage.initialize(DbLedgerStorage.java:150)
~[org.apache.bookkeeper-bookkeeper-server-4.15.0-SNAPSHOT.jar:4.15.0-SNAPSHOT]
at
org.apache.bookkeeper.bookie.BookieResources.createLedgerStorage(BookieResources.java:110)
~[org.apache.bookkeeper-bookkeeper-server-4.15.0-SNAPSHOT.jar:4.15.0-SNAPSHOT]
at
org.apache.pulsar.zookeeper.LocalBookkeeperEnsemble.buildBookie(LocalBookkeeperEnsemble.java:328)
~[org.apache.pulsar-pulsar-zookeeper-utils-2.8.1.jar:2.8.1]
at
org.apache.pulsar.zookeeper.LocalBookkeeperEnsemble.runBookies(LocalBookkeeperEnsemble.java:391)
~[org.apache.pulsar-pulsar-zookeeper-utils-2.8.1.jar:2.8.1]
at
org.apache.pulsar.zookeeper.LocalBookkeeperEnsemble.startStandalone(LocalBookkeeperEnsemble.java:521)
~[org.apache.pulsar-pulsar-zookeeper-utils-2.8.1.jar:2.8.1]
at
org.apache.pulsar.PulsarStandalone.start(PulsarStandalone.java:264)
~[org.apache.pulsar-pulsar-broker-2.8.1.jar:2.8.1]
at
org.apache.pulsar.PulsarStandaloneStarter.main(PulsarStandaloneStarter.java:121)
[org.apache.pulsar-pulsar-broker-2.8.1.jar:2.8.1]
Caused by: org.rocksdb.RocksDBException: lock hold by current process,
acquire time 1640492668 acquiring thread 123145515651072:
data/standalone/bookkeeper00/entrylogIndexCache/metadata-cache/LOCK: No locks
available
at org.rocksdb.RocksDB.open(Native Method)
~[org.rocksdb-rocksdbjni-6.10.2.jar:?]
at org.rocksdb.RocksDB.open(RocksDB.java:239)
~[org.rocksdb-rocksdbjni-6.10.2.jar:?]
at
org.apache.bookkeeper.bookie.storage.ldb.KeyValueStorageRocksDB.<init>(KeyValueStorageRocksDB.java:199)
~[org.apache.bookkeeper-bookkeeper-server-4.15.0-SNAPSHOT.jar:4.15.0-SNAPSHOT]
... 15 more
```
The reason is multi garbageCollectionThread will open the same RocksDB and
own the LOCK, and then throw the above exception.
### Modification
1. Change the default GcEntryLogMetadataCachePath from
`getLedgerDirNames()[0] + "/" + ENTRYLOG_INDEX_CACHE` to `null`. If it is
`null`, it will use each ledger's directory.
2. Remove the internal directory `entrylogIndexCache`. The data structure
looks like:
```
└── current
├── lastMark
├── ledgers
│ ├── 000003.log
│ ├── CURRENT
│ ├── IDENTITY
│ ├── LOCK
│ ├── LOG
│ ├── MANIFEST-000001
│ └── OPTIONS-000005
├── locations
│ ├── 000003.log
│ ├── CURRENT
│ ├── IDENTITY
│ ├── LOCK
│ ├── LOG
│ ├── MANIFEST-000001
│ └── OPTIONS-000005
└── metadata-cache
├── 000003.log
├── CURRENT
├── IDENTITY
├── LOCK
├── LOG
├── MANIFEST-000001
└── OPTIONS-000005
```
3. If user configured `GcEntryLogMetadataCachePath` in `bk_server.conf`, it
only support one ledger directory configured for `ledgerDirectories`.
Otherwise, the best practice is to keep it default.
4. The PR is better to release with #1949
---
.../java/org/apache/bookkeeper/bookie/BookieImpl.java | 11 +++++++----
.../bookkeeper/bookie/GarbageCollectorThread.java | 17 +++++++++++++----
.../bookkeeper/bookie/InterleavedLedgerStorage.java | 3 ++-
.../storage/ldb/PersistentEntryLogMetadataMap.java | 5 +++--
.../storage/ldb/SingleDirectoryDbLedgerStorage.java | 2 +-
.../org/apache/bookkeeper/conf/ServerConfiguration.java | 12 +++++++-----
.../org/apache/bookkeeper/util/BookKeeperConstants.java | 2 +-
7 files changed, 34 insertions(+), 18 deletions(-)
diff --git
a/bookkeeper-server/src/main/java/org/apache/bookkeeper/bookie/BookieImpl.java
b/bookkeeper-server/src/main/java/org/apache/bookkeeper/bookie/BookieImpl.java
index f0a002f..94b7525 100644
---
a/bookkeeper-server/src/main/java/org/apache/bookkeeper/bookie/BookieImpl.java
+++
b/bookkeeper-server/src/main/java/org/apache/bookkeeper/bookie/BookieImpl.java
@@ -25,6 +25,7 @@ import static
org.apache.bookkeeper.bookie.BookKeeperServerStats.JOURNAL_SCOPE;
import static
org.apache.bookkeeper.bookie.BookKeeperServerStats.LD_INDEX_SCOPE;
import static
org.apache.bookkeeper.bookie.BookKeeperServerStats.LD_LEDGER_SCOPE;
import com.google.common.annotations.VisibleForTesting;
+import com.google.common.base.Strings;
import com.google.common.collect.Lists;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.ByteBufAllocator;
@@ -1192,10 +1193,12 @@ public class BookieImpl extends BookieCriticalThread
implements Bookie {
// Clean up metadata directories if they are separate from the
// ledger dirs
- File metadataDir = new File(conf.getGcEntryLogMetadataCachePath());
- if (!cleanDir(metadataDir)) {
- LOG.error("Formatting ledger metadata directory {} failed",
metadataDir);
- return false;
+ if (!Strings.isNullOrEmpty(conf.getGcEntryLogMetadataCachePath())) {
+ File metadataDir = new File(conf.getGcEntryLogMetadataCachePath());
+ if (!cleanDir(metadataDir)) {
+ LOG.error("Formatting ledger metadata directory {} failed",
metadataDir);
+ return false;
+ }
}
LOG.info("Bookie format completed successfully");
return true;
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 8e46a63..123ab14 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
@@ -21,7 +21,9 @@
package org.apache.bookkeeper.bookie;
+import static org.apache.bookkeeper.util.BookKeeperConstants.METADATA_CACHE;
import com.google.common.annotations.VisibleForTesting;
+import com.google.common.base.Strings;
import io.netty.util.concurrent.DefaultThreadFactory;
import java.io.IOException;
@@ -121,6 +123,7 @@ public class GarbageCollectorThread extends SafeRunnable {
final GarbageCleaner garbageCleaner;
final ServerConfiguration conf;
+ final LedgerDirsManager ledgerDirsManager;
/**
* Create a garbage collector thread.
@@ -130,8 +133,10 @@ public class GarbageCollectorThread extends SafeRunnable {
* @throws IOException
*/
public GarbageCollectorThread(ServerConfiguration conf, LedgerManager
ledgerManager,
- final CompactableLedgerStorage ledgerStorage, StatsLogger
statsLogger) throws IOException {
- this(conf, ledgerManager, ledgerStorage, statsLogger,
+ final LedgerDirsManager ledgerDirsManager,
+ final CompactableLedgerStorage ledgerStorage,
+ StatsLogger statsLogger) throws IOException {
+ this(conf, ledgerManager, ledgerDirsManager, ledgerStorage,
statsLogger,
Executors.newSingleThreadScheduledExecutor(new
DefaultThreadFactory("GarbageCollectorThread")));
}
@@ -144,6 +149,7 @@ public class GarbageCollectorThread extends SafeRunnable {
*/
public GarbageCollectorThread(ServerConfiguration conf,
LedgerManager ledgerManager,
+ final LedgerDirsManager ledgerDirsManager,
final CompactableLedgerStorage ledgerStorage,
StatsLogger statsLogger,
ScheduledExecutorService gcExecutor)
@@ -151,6 +157,7 @@ public class GarbageCollectorThread extends SafeRunnable {
this.gcExecutor = gcExecutor;
this.conf = conf;
+ this.ledgerDirsManager = ledgerDirsManager;
this.entryLogger = ledgerStorage.getEntryLogger();
this.entryLogMetaMap = createEntryLogMetadataMap();
this.ledgerStorage = ledgerStorage;
@@ -261,11 +268,13 @@ public class GarbageCollectorThread extends SafeRunnable {
private EntryLogMetadataMap createEntryLogMetadataMap() throws IOException
{
if (conf.isGcEntryLogMetadataCacheEnabled()) {
- String baseDir = this.conf.getGcEntryLogMetadataCachePath();
+ String baseDir =
Strings.isNullOrEmpty(conf.getGcEntryLogMetadataCachePath())
+ ? this.ledgerDirsManager.getAllLedgerDirs().get(0).getPath() :
conf.getGcEntryLogMetadataCachePath();
try {
return new PersistentEntryLogMetadataMap(baseDir, conf);
} catch (IOException e) {
- LOG.error("Failed to initialize persistent-metadata-map ,
clean up {}", baseDir, e);
+ LOG.error("Failed to initialize persistent-metadata-map ,
clean up {}",
+ baseDir + "/" + METADATA_CACHE, e);
throw e;
}
} else {
diff --git
a/bookkeeper-server/src/main/java/org/apache/bookkeeper/bookie/InterleavedLedgerStorage.java
b/bookkeeper-server/src/main/java/org/apache/bookkeeper/bookie/InterleavedLedgerStorage.java
index dcfeed0..0960c66 100644
---
a/bookkeeper-server/src/main/java/org/apache/bookkeeper/bookie/InterleavedLedgerStorage.java
+++
b/bookkeeper-server/src/main/java/org/apache/bookkeeper/bookie/InterleavedLedgerStorage.java
@@ -193,7 +193,8 @@ public class InterleavedLedgerStorage implements
CompactableLedgerStorage, Entry
this.entryLogger.addListener(this);
ledgerCache = new LedgerCacheImpl(conf, activeLedgers,
null == indexDirsManager ? ledgerDirsManager :
indexDirsManager, statsLogger);
- gcThread = new GarbageCollectorThread(conf, ledgerManager, this,
statsLogger.scope("gc"));
+ gcThread = new GarbageCollectorThread(conf, ledgerManager,
ledgerDirsManager,
+ this, statsLogger.scope("gc"));
pageSize = conf.getPageSize();
ledgerDirsManager.addLedgerDirsListener(getLedgerDirsListener());
// Expose Stats
diff --git
a/bookkeeper-server/src/main/java/org/apache/bookkeeper/bookie/storage/ldb/PersistentEntryLogMetadataMap.java
b/bookkeeper-server/src/main/java/org/apache/bookkeeper/bookie/storage/ldb/PersistentEntryLogMetadataMap.java
index 812ab84..95b3659 100644
---
a/bookkeeper-server/src/main/java/org/apache/bookkeeper/bookie/storage/ldb/PersistentEntryLogMetadataMap.java
+++
b/bookkeeper-server/src/main/java/org/apache/bookkeeper/bookie/storage/ldb/PersistentEntryLogMetadataMap.java
@@ -20,6 +20,7 @@
*/
package org.apache.bookkeeper.bookie.storage.ldb;
+import static org.apache.bookkeeper.util.BookKeeperConstants.METADATA_CACHE;
import io.netty.util.concurrent.FastThreadLocal;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
@@ -77,14 +78,14 @@ public class PersistentEntryLogMetadataMap implements
EntryLogMetadataMap {
};
public PersistentEntryLogMetadataMap(String metadataPath,
ServerConfiguration conf) throws IOException {
- LOG.info("Loading persistent entrylog metadata-map from {}",
metadataPath);
+ LOG.info("Loading persistent entrylog metadata-map from {}",
metadataPath + "/" + METADATA_CACHE);
File dir = new File(metadataPath);
if (!dir.mkdirs() && !dir.exists()) {
String err = "Unable to create directory " + dir;
LOG.error(err);
throw new IOException(err);
}
- metadataMapDB =
KeyValueStorageRocksDB.factory.newKeyValueStorage(metadataPath,
"metadata-cache",
+ metadataMapDB =
KeyValueStorageRocksDB.factory.newKeyValueStorage(metadataPath, METADATA_CACHE,
DbConfigType.Small, conf);
}
diff --git
a/bookkeeper-server/src/main/java/org/apache/bookkeeper/bookie/storage/ldb/SingleDirectoryDbLedgerStorage.java
b/bookkeeper-server/src/main/java/org/apache/bookkeeper/bookie/storage/ldb/SingleDirectoryDbLedgerStorage.java
index 4d2e4ad..ce8af36 100644
---
a/bookkeeper-server/src/main/java/org/apache/bookkeeper/bookie/storage/ldb/SingleDirectoryDbLedgerStorage.java
+++
b/bookkeeper-server/src/main/java/org/apache/bookkeeper/bookie/storage/ldb/SingleDirectoryDbLedgerStorage.java
@@ -183,7 +183,7 @@ public class SingleDirectoryDbLedgerStorage implements
CompactableLedgerStorage
TransientLedgerInfo.LEDGER_INFO_CACHING_TIME_MINUTES,
TimeUnit.MINUTES);
entryLogger = new EntryLogger(conf, ledgerDirsManager, null,
statsLogger, allocator);
- gcThread = new GarbageCollectorThread(conf, ledgerManager, this,
statsLogger);
+ gcThread = new GarbageCollectorThread(conf, ledgerManager,
ledgerDirsManager, this, statsLogger);
dbLedgerStorageStats = new DbLedgerStorageStats(
ledgerDirStatsLogger,
diff --git
a/bookkeeper-server/src/main/java/org/apache/bookkeeper/conf/ServerConfiguration.java
b/bookkeeper-server/src/main/java/org/apache/bookkeeper/conf/ServerConfiguration.java
index a587145..3f099eb 100644
---
a/bookkeeper-server/src/main/java/org/apache/bookkeeper/conf/ServerConfiguration.java
+++
b/bookkeeper-server/src/main/java/org/apache/bookkeeper/conf/ServerConfiguration.java
@@ -17,7 +17,6 @@
*/
package org.apache.bookkeeper.conf;
-import static
org.apache.bookkeeper.util.BookKeeperConstants.ENTRYLOG_INDEX_CACHE;
import static
org.apache.bookkeeper.util.BookKeeperConstants.MAX_LOG_SIZE_LIMIT;
import com.google.common.annotations.Beta;
@@ -515,17 +514,20 @@ public class ServerConfiguration extends
AbstractConfiguration<ServerConfigurati
* gcPersistentEntrylogMetadataMapEnabled is true.
*
* @return entrylog metadata-map persistent store dir path.(default: it
- * creates a sub-directory under a first available base ledger
- * directory with name "entrylogIndexCache").
+ * creates a sub-directory under each ledger
+ * directory with name "metadata-cache". If it set, it only works
for one ledger directory
+ * configured for ledgerDirectories).
*/
public String getGcEntryLogMetadataCachePath() {
- return getString(GC_ENTRYLOG_METADATA_CACHE_PATH,
getLedgerDirNames()[0] + "/" + ENTRYLOG_INDEX_CACHE);
+ return getString(GC_ENTRYLOG_METADATA_CACHE_PATH, null);
}
/**
* Set directory to persist Entrylog metadata if
gcPersistentEntrylogMetadataMapEnabled is true.
+ * If it set, it only works for one ledger directory configured for
ledgerDirectories. For multi ledgerDirectory
+ * configured, keep the default value is the best practice.
*
- * @param gcPersistentEntrylogMetadataMapPath.
+ * @param gcEntrylogMetadataCachePath
* @return server configuration.
*/
public ServerConfiguration setGcEntryLogMetadataCachePath(String
gcEntrylogMetadataCachePath) {
diff --git
a/bookkeeper-server/src/main/java/org/apache/bookkeeper/util/BookKeeperConstants.java
b/bookkeeper-server/src/main/java/org/apache/bookkeeper/util/BookKeeperConstants.java
index 8e10a15..d928aac 100644
---
a/bookkeeper-server/src/main/java/org/apache/bookkeeper/util/BookKeeperConstants.java
+++
b/bookkeeper-server/src/main/java/org/apache/bookkeeper/util/BookKeeperConstants.java
@@ -31,7 +31,7 @@ public class BookKeeperConstants {
public static final String BOOKIE_STATUS_FILENAME = "BOOKIE_STATUS";
public static final String PASSWD = "passwd";
public static final String CURRENT_DIR = "current";
- public static final String ENTRYLOG_INDEX_CACHE = "entrylogIndexCache";
+ public static final String METADATA_CACHE = "metadata-cache";
public static final String READONLY = "readonly";
// //////////////////////////