-
Notifications
You must be signed in to change notification settings - Fork 14k
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
KAFKA-3968: fsync the parent directory of a segment file when the file is created #10405
Merged
Merged
Changes from all commits
Commits
Show all changes
27 commits
Select commit
Hold shift + click to select a range
459facb
[KAFKA-3968] fsync the parent directory of a segment file when the fi…
ccding b4c8284
move import
ccding b260169
address comments (except the topic partition one)
ccding ba086e9
remove import
ccding 2a19e0e
reuse the function in utils.java
ccding 40a1abe
simplify logic
ccding 1ac80b6
default changeFileSuffixes flush to true
ccding 09cac0b
flush when mkdirs
ccding 5be95aa
revert accidential change
ccding c9448c8
atomicMoveWithFallback
ccding daeb698
no flush parent dir in test
ccding 0d4800b
check null pointer
ccding 95a6c3f
fix unit test error
ccding 8c859f3
set flag after flush
ccding fdc1faa
disable flushing on renameTo
ccding 6795ec9
address comments based on offline discussion with Jun
ccding 55ae3bc
Merge branch 'trunk' into fsync
ccding e653af4
check hadCleanShutdown for open FileRecord
ccding 85861ee
address comments
ccding 1578678
fix default values
ccding fffc353
more default value
ccding f66c545
do flush in the LogSegment class
ccding 56be9d8
Merge branch 'trunk' into fsync
ccding 1ecf94b
remove parameter from FileRecord.open
ccding 080a79a
default to false
ccding 61eee4a
add param to javadoc
ccding 7543938
during flush -> during the next flush
ccding File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -20,6 +20,7 @@ import java.io.{File, IOException} | |
import java.nio.file.{Files, NoSuchFileException} | ||
import java.nio.file.attribute.FileTime | ||
import java.util.concurrent.TimeUnit | ||
import java.util.concurrent.atomic.AtomicBoolean | ||
import kafka.common.LogSegmentOffsetOverflowException | ||
import kafka.metrics.{KafkaMetricsGroup, KafkaTimer} | ||
import kafka.server.epoch.LeaderEpochFileCache | ||
|
@@ -50,6 +51,7 @@ import scala.math._ | |
* @param indexIntervalBytes The approximate number of bytes between entries in the index | ||
* @param rollJitterMs The maximum random jitter subtracted from the scheduled segment roll time | ||
* @param time The time instance | ||
* @param needsFlushParentDir Whether or not we need to flush the parent directory during the first flush | ||
*/ | ||
@nonthreadsafe | ||
class LogSegment private[log] (val log: FileRecords, | ||
|
@@ -59,7 +61,8 @@ class LogSegment private[log] (val log: FileRecords, | |
val baseOffset: Long, | ||
val indexIntervalBytes: Int, | ||
val rollJitterMs: Long, | ||
val time: Time) extends Logging { | ||
val time: Time, | ||
val needsFlushParentDir: Boolean = false) extends Logging { | ||
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. Could we add the new param to the javadoc? 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. Done. |
||
|
||
def offsetIndex: OffsetIndex = lazyOffsetIndex.get | ||
|
||
|
@@ -95,6 +98,9 @@ class LogSegment private[log] (val log: FileRecords, | |
/* the number of bytes since we last added an entry in the offset index */ | ||
private var bytesSinceLastIndexEntry = 0 | ||
|
||
/* whether or not we need to flush the parent dir during the next flush */ | ||
private val atomicNeedsFlushParentDir = new AtomicBoolean(needsFlushParentDir) | ||
|
||
// The timestamp we used for time based log rolling and for ensuring max compaction delay | ||
// volatile for LogCleaner to see the update | ||
@volatile private var rollingBasedTimestamp: Option[Long] = None | ||
|
@@ -472,6 +478,9 @@ class LogSegment private[log] (val log: FileRecords, | |
offsetIndex.flush() | ||
timeIndex.flush() | ||
txnIndex.flush() | ||
// We only need to flush the parent of the log file because all other files share the same parent | ||
if (atomicNeedsFlushParentDir.getAndSet(false)) | ||
log.flushParentDir() | ||
} | ||
} | ||
|
||
|
@@ -490,11 +499,14 @@ class LogSegment private[log] (val log: FileRecords, | |
* Change the suffix for the index and log files for this log segment | ||
* IOException from this method should be handled by the caller | ||
*/ | ||
def changeFileSuffixes(oldSuffix: String, newSuffix: String): Unit = { | ||
def changeFileSuffixes(oldSuffix: String, newSuffix: String, needsFlushParentDir: Boolean = true): Unit = { | ||
log.renameTo(new File(CoreUtils.replaceSuffix(log.file.getPath, oldSuffix, newSuffix))) | ||
lazyOffsetIndex.renameTo(new File(CoreUtils.replaceSuffix(lazyOffsetIndex.file.getPath, oldSuffix, newSuffix))) | ||
lazyTimeIndex.renameTo(new File(CoreUtils.replaceSuffix(lazyTimeIndex.file.getPath, oldSuffix, newSuffix))) | ||
txnIndex.renameTo(new File(CoreUtils.replaceSuffix(txnIndex.file.getPath, oldSuffix, newSuffix))) | ||
// We only need to flush the parent of the log file because all other files share the same parent | ||
if (needsFlushParentDir) | ||
log.flushParentDir() | ||
} | ||
|
||
/** | ||
|
@@ -657,7 +669,8 @@ class LogSegment private[log] (val log: FileRecords, | |
object LogSegment { | ||
|
||
def open(dir: File, baseOffset: Long, config: LogConfig, time: Time, fileAlreadyExists: Boolean = false, | ||
initFileSize: Int = 0, preallocate: Boolean = false, fileSuffix: String = ""): LogSegment = { | ||
initFileSize: Int = 0, preallocate: Boolean = false, fileSuffix: String = "", | ||
needsRecovery: Boolean = false): LogSegment = { | ||
val maxIndexSize = config.maxIndexSize | ||
new LogSegment( | ||
FileRecords.open(Log.logFile(dir, baseOffset, fileSuffix), fileAlreadyExists, initFileSize, preallocate), | ||
|
@@ -667,7 +680,8 @@ object LogSegment { | |
baseOffset, | ||
indexIntervalBytes = config.indexInterval, | ||
rollJitterMs = config.randomSegmentJitter, | ||
time) | ||
time, | ||
needsFlushParentDir = needsRecovery || !fileAlreadyExists) | ||
} | ||
|
||
def deleteIfExists(dir: File, baseOffset: Long, fileSuffix: String = ""): Unit = { | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
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 am wondering if we should flush the parent dir when we delete a log too. This is not strictly required for every delete. So one option is to flush every parent dir when closing the LogManager.
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.
Per our offline discussion, we decided not to flush at deletion. Deletions are async and can be retried after rebooting.