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.
Before this PR
The cluster controller distributes
ServerDBInfothrough a relay tree. A simplified version of the failure we encountered looked like this:The failure followed this timeline:
The cluster controller detects that
storage-0is unavailable.workerAvailabilityWatch()useswaitFailureClient()to require the failure to remain continuous forSERVER_KNOBS->WORKER_FAILURE_TIME(default: 1 second) before removing the worker. During that second,storage-0remains inid_worker.ServerDBInfochanges during that one-second window.dbInfoUpdater()builds the broadcast target list fromid_worker. Becausestorage-0has not been removed yet, the new relay tree includes it. In this example, the cluster controller sends the broadcast tostateless-0and assignsstorage-0as one of its children.If the broadcast had started after
WORKER_FAILURE_TIMEelapsed,storage-0would already have been removed and would not have appeared in the tree.The cluster controller removes
storage-0.The one-second failure interval expires and
removeFailedWorker()removesstorage-0fromid_worker. Before this PR, removal did not interrupt the active broadcast, whose target list still containedstorage-0.stateless-0independently detects the same failure.The request from the cluster controller to
stateless-0remains healthy, so the cluster controller continues waiting for the relay. The relay must discover that its child is unreachable using its own failure monitor:FLOW_KNOBS->CONNECTION_MONITOR_TIMEOUT(default: 2 seconds outside simulation) before marking the connection failed.getReplyUnlessFailedFor()then requires the child to remain failed forSERVER_KNOBS->DBINFO_FAILED_DELAY(default: 1 second).The broadcast finishes approximately three seconds after it started.
Only after those relay-local failure delays can
stateless-0report the failed endpoint to the cluster controller. This delayed transaction-server initialization even though the cluster controller had already removed the worker blocking the relay.After this PR
The first part of the timeline is unchanged:
storage-0remains inid_workerduringWORKER_FAILURE_TIME.ServerDBInfobroadcast that starts during this window may initially includestorage-0.The behavior changes when the one-second failure interval expires:
Removing
storage-0interrupts the active broadcast.removeFailedWorker()now triggersupdateDBInfo. The existing interruption path indbInfoUpdater():SERVER_KNOBS->DBINFO_BATCH_DELAY(default: 0.1 seconds).The replacement broadcast excludes
storage-0.The cluster controller no longer waits for
stateless-0to spend approximately two seconds detecting the failed connection followed by another second ofDBINFO_FAILED_DELAY.Requests already delivered to the original relay tree are not remotely cancelled.
stateless-0may continue its old relay work, but that work no longer gates the replacement broadcast or recovery.The steady-state path is unchanged because the new trigger only runs after the cluster controller removes a worker.
Possible downsides
Restarting a broadcast can duplicate work. Requests already delivered to relays may continue while the replacement round sends the same, idempotent
ServerDBInfoupdate. Staggered worker failures can therefore increase network and CPU usage, and sustained worker churn can repeatedly restart the cluster controller's local tracking of the broadcast.A worker removal that was not blocking the active broadcast can also cause an unnecessary replacement round.
DBINFO_BATCH_DELAYcoalesces removals that happen close together, and already-delivered requests continue running.Testing
fdbserver_clustercontroller_test: 33 passed, 0 failed.git diff --checkpassed.No new unit test is included. A direct unit test would only assert that the new trigger wakes
dbInfoUpdater; it would not reproduce the independent failure-monitor state that caused the three-second delay.