[server] Add configurable retry and cleanup for remote log segment uploads - #3775
Open
XuQianJin-Stars wants to merge 1 commit into
Open
[server] Add configurable retry and cleanup for remote log segment uploads#3775XuQianJin-Stars wants to merge 1 commit into
XuQianJin-Stars wants to merge 1 commit into
Conversation
This file contains hidden or 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
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
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.
Purpose
DefaultRemoteLogStorage#copyLogSegmentFilesin thefluss-servermoduleperforms a single-shot upload of the log segment + offset index + time index +
producer-snapshot files. When a single file upload fails with a transient
remote I/O error — a 5xx from COS / S3 / OSS / OBS, a brief network blip,
etc. — the whole segment copy currently fails and the failure bubbles up to
LogTieringTask, which then has to re-stage the entire segment from scratch.In the common case where, say, 3 of the 4 files (log + indexes) have already
been uploaded successfully, this leaves behind a "partial segment directory"
on the remote side that is only cleaned up by a later periodic GC pass. It
wastes space, can confuse monitoring/alerting, and amplifies the recovery
workload after a transient outage.
This PR adds two improvements:
IOException, using the existingorg.apache.fluss.utils.ExponentialBackoffutility (same pattern asRemoteLogFetcher#downloadSegmentWithRetry).ultimately fails, so a half-staged segment does not linger.
Linked issue: N/A (server-side robustness improvement for tiering uploads)
Brief change log
Add two new
ConfigOptions influss-common/src/main/java/org/apache/fluss/config/ConfigOptions.java,next to the existing
REMOTE_LOG_*block:remote.log.upload.retry.max-attempts(default3, typeint) — maxretry attempts per file. Set to
0to disable retries.remote.log.upload.retry.initial-backoff(default200ms, typeDuration) — initial exponential-backoff delay. The actual delay isinitial * multiplier^attemptwithmultiplier=2, capped at10s, plus20% jitter to avoid thundering-herd retries.
Update
DefaultRemoteLogStorageinfluss-server/src/main/java/org/apache/fluss/server/log/remote/DefaultRemoteLogStorage.java:retryMaxAttemptsandretryBackofffields; read both options inthe constructor.
@VisibleForTestingwriteToRemoteWithRetry(Path, FsPath, String)method that opens a freshInputStreamper attempt and rethrowsthe last
IOExceptionwhen all retries are exhausted (mirrors theretry pattern in
RemoteLogFetcher).createUploadFuturesworker fromwriteToRemote(...)towriteToRemoteWithRetry(localFile, rlsPath, fileName)so each filegets its own retry loop.
ExecutionException/ genericExceptioninsidecopyLogSegmentFiles, call a newcleanupSegmentFilesQuietly(...)helper that invokes the existing
deleteLogSegmentFiles(...)to removethe partially uploaded segment directory. Cleanup failures are logged
and swallowed so the original cause is preserved.
writeToRemoteandwriteToRemoteWithRetrypackage-private with@VisibleForTestingso the retry test can subclass and inject failures.No public API change.
RemoteLogStorageinterface,RemoteLogManagerand the surrounding tiering pipeline are untouched.
Tests
fluss-server/src/test/java/org/apache/fluss/server/log/remote/DefaultRemoteLogStorageRetryTest.javawith 4 focused tests, all of which use a
RetryingRemoteLogStoragesubclass that fails the first N
writeToRemoteinvocations:testUploadRetriesAndSucceedsOnSecondAttempt— configuresretry.max-attempts=3/initial-backoff=1ms, fails the first upload,then asserts the segment is fully uploaded and the underlying
writeToRemotecall count is> 4(proving the retry actuallyre-opened the input stream).
testUploadFailsAfterAllRetriesExhausted— configures 2 retries,always-failing storage, asserts
RemoteStorageExceptionis thrown andthe call count is
>= 3 * files(every file retried 3 times).testPartialUploadCleanupOnFailure— configures 0 retries, assertsRemoteStorageExceptionand that at least onewriteToRemotewasattempted (proving the cleanup-on-failure path was reached).
testNoRetryWhenMaxAttemptsIsZero— configures 0 retries, assertswriteToRemoteis called exactly 4 times (once per file, no retry),locking in the "disable retries" semantics.
DefaultRemoteLogStorageTestcontinue to pass (no regression). Testsrun against a real local filesystem via the existing
RemoteLogTestBaseharness.
API and Format
RemoteLogStorageandDefaultRemoteLogStoragekeep their public surface. Newly package-privatemethods (
writeToRemoteWithRetry,writeToRemote) are annotated with@VisibleForTestingfromorg.apache.fluss.annotation.AGENTS.md §8 Configuration Patterns: explicit
intType()/durationType(), explicitdefaultValue(...), and javadocwithDescription(...)with the K8s / transient-error rationale.mvn spotless:applyclean.var, noOptional.isEmpty, noList.of,no
CompletableFuture.failedFuture(...)(Java 9+).assertThat(...),assertThatThrownBy).ExponentialBackoffis reused fromorg.apache.fluss.utils— no newdependency introduced.
[server] Add configurable retry and cleanup for remote log segment uploadsfollows the<component>prefix convention../mvnw clean install -DskipTests -T 32passes locally on JDK11.0.23-kona.mvn test -pl fluss-server -Dtest=DefaultRemoteLogStorageRetryTestpasses (4/4).
Documentation
withDescription(...)javadoc, so theywill be picked up by
./mvnw -pl fluss-docgen verifyautomatically andrendered in the generated config reference. No manual website change is
required.
(
WARNon retry,DEBUGon successful cleanup,WARNon cleanupfailure), so operators can verify it from server logs without new metric
names.