-
Notifications
You must be signed in to change notification settings - Fork 15.1k
KAFKA-15633: Fix overwrite of meta.properties at startup to handle JBOD. #14578
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
4e99467
ed86a4a
26967e3
c7f7104
7832a72
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -270,26 +270,38 @@ class LogManager(logDirs: Seq[File], | |
| def directoryId(dir: String): Option[Uuid] = dirIds.get(dir) | ||
|
|
||
| /** | ||
| * Determine directory ID for each directory with a meta.properties. | ||
| * Determine directory ID for each directory. | ||
| * If meta.properties does not include a directory ID, one is generated and persisted back to meta.properties. | ||
| * Directories without a meta.properties don't get a directory ID assigned. | ||
| * Directories without a meta.properties file, which can only occur in Zk mode, will file have a directory ID assigned. | ||
| * The ID will be written when the new meta.properties file is first written. | ||
| */ | ||
| private def directoryIds(dirs: Seq[File]): Map[String, Uuid] = { | ||
| val s = scala.collection.mutable.Set[Uuid]() | ||
| dirs.flatMap { dir => | ||
| try { | ||
| val metadataCheckpoint = new BrokerMetadataCheckpoint(new File(dir, KafkaServer.brokerMetaPropsFile)) | ||
| metadataCheckpoint.read().map { props => | ||
| val rawMetaProperties = new RawMetaProperties(props) | ||
| val uuid = rawMetaProperties.directoryId match { | ||
| case Some(uuidStr) => Uuid.fromString(uuidStr) | ||
| case None => | ||
| val uuid = Uuid.randomUuid() | ||
| rawMetaProperties.directoryId = uuid.toString | ||
| metadataCheckpoint.write(rawMetaProperties.props) | ||
| uuid | ||
| val uuid = metadataCheckpoint.read() match { | ||
| case Some(props) => { | ||
| val rawMetaProperties = new RawMetaProperties(props) | ||
| val uuid_from_properties = rawMetaProperties.directoryId match { | ||
| case Some(uuidStr) => Uuid.fromString(uuidStr) | ||
| case None => | ||
| val uuid_new = Uuid.randomUuid() | ||
| rawMetaProperties.directoryId = uuid_new.toString | ||
| metadataCheckpoint.write(rawMetaProperties.props) | ||
| uuid_new | ||
| } | ||
| uuid_from_properties | ||
| } | ||
| case None => { | ||
| Uuid.randomUuid() | ||
| } | ||
| dir.getAbsolutePath -> uuid | ||
| }.toMap | ||
| } | ||
| if (s.contains(uuid)) { | ||
| throw new RuntimeException(s"Found duplicate directory.ids ${uuid.toString}") | ||
| } | ||
|
Comment on lines
+300
to
+302
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. An alternative to maintaining a mutable set and modifying it from within the flatMap lamda could be to compare the size of the result with if (dirIds.values.toSet.size != dirIds.values.size)
throw new RuntimeException(s"Found duplicate directory.ids ${uuid.toString}")
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Perhaps |
||
| s += uuid | ||
| Seq(dir.getAbsolutePath -> uuid) | ||
| } catch { | ||
| case e: IOException => | ||
| logDirFailureChannel.maybeAddOfflineLogDir(dir.getAbsolutePath, s"Disk error while loading ID $dir", e) | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -166,6 +166,7 @@ case class MetaProperties( | |
| } | ||
| } | ||
|
|
||
| // Return only the RawMetaProperties that are the same across all directories. | ||
| object BrokerMetadataCheckpoint extends Logging { | ||
| def getBrokerMetadataAndOfflineDirs( | ||
| logDirs: collection.Seq[String], | ||
|
|
@@ -184,6 +185,8 @@ object BrokerMetadataCheckpoint extends Logging { | |
| try { | ||
| brokerCheckpoint.read() match { | ||
| case Some(properties) => | ||
| // XXX Should we check for duplicates here | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Is
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I've added it there. Let me know what you think |
||
| properties.remove(DirectoryIdKey) | ||
| brokerMetadataMap += logDir -> properties | ||
| case None => | ||
| if (!ignoreMissing) { | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm not sure about this, maybe I'm missing something. So if meta.properties does not exist for some directory, we generate a random one, but it seems the generated value isn't persisted? That means the same log directory will get a different ID ever time the broker restarts, which will generate a lot of unnecessary reassignments...
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It will get persisted. The only case where we allow a directory to not have a meta.properties file is in Zk mode. In Zk mode on startup, all directories without a meta.properties file have one created immediately after the broker is registered with ZooKeeper.