[
https://issues.apache.org/jira/browse/HDDS-17576?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel
]
Siyao Meng updated HDDS-17576:
------------------------------
Affects Version/s: 2.2.1
2.0.0
1.2.1
1.4.0
1.2.0
2.1.2
2.1.0
1.4.1
2.1.1
1.3.0
2.2.0
> Follower SCM stops applying the Raft log until restart after an install
> snapshot notification from a leader missing from its peer list
> --------------------------------------------------------------------------------------------------------------------------------------
>
> Key: HDDS-17576
> URL: https://issues.apache.org/jira/browse/HDDS-17576
> Project: Apache Ozone
> Issue Type: Bug
> Affects Versions: 1.2.0, 1.3.0, 1.2.1, 1.4.0, 2.0.0, 1.4.1, 2.1.0, 2.2.0,
> 2.1.1, 2.1.2, 2.2.1
> Reporter: Siyao Meng
> Priority: Minor
> Attachments:
> MC-3-fail-install-snapshot-future-for-unknown-scm-leader.patch,
> TestBugMC3FollowerStuckAfterInstallNotification.java
>
>
> h3. Mechanism
> {{SCMStateMachine.notifyInstallSnapshotFromLeader}} looks the leader up by
> its Ratis address in {{SCMHANodeDetails.getPeerNodeDetails}} and runs
> {{Preconditions.checkState(leaderDetails.isPresent())}} on the calling Ratis
> thread. When no peer matches it throws {{IllegalStateException}} instead of
> returning a failed future, as the "missing leader info" branch just above it
> does.
> Ratis ({{SnapshotInstallationHandler.notifyStateMachineToInstallSnapshot}},
> 3.3.1) has already set its in-progress install index at that point and clears
> it on failure only in the {{whenComplete}} of the returned future. The
> synchronous exception skips that, and nothing else resets the index. From
> then on the division refuses every {{appendEntries}} ("installation is in
> progress") and answers every later install notification with {{IN_PROGRESS}}
> (or an error, when a later leader's first available index is below the stale
> one) without calling the state machine again, also when the leader is an SCM
> it knows. The index is only in memory, so a restart of the SCM should clear
> it (argued, a restart was not run).
> RATIS-1417 added a catch for this case on Ratis master in 2021, but it was
> removed again by RATIS-1481 before the next release, so no Ratis release used
> by Ozone has it.
> h3. Trigger
> The peer list is read from the configuration once, when the
> {{StorageContainerManager}} is constructed. A running SCM therefore does not
> know an SCM that was bootstrapped after it started:
> # Three SCMs with {{ozone.scm.ha.ratis.log.purge.enabled}} set to true.
> Bootstrap a fourth SCM and make it leader ({{ozone admin scm transfer}}, or
> an election).
> # One of the original followers, still running, falls behind the new leader's
> purged log (network partition, long pause) far enough that the purge passes
> its next index; the leader purges in steps of at least
> {{ozone.scm.ha.ratis.log.purge.gap}} (default 1000000 entries) (argued from
> code).
> # The new leader sends it an install snapshot notification. Its address is
> not in the follower's peer list, and the follower is stuck.
> With the default {{ozone.scm.ha.ratis.log.purge.enabled=false}} the leader
> purges only up to the lowest commit index of its peers, so a lagging follower
> keeps receiving entries and is not sent an install notification; a follower
> that is restarted instead loads the updated peer list (both argued from code,
> not run). An address mismatch between the configured peers and the Ratis peer
> address (HDDS-17205) leads to the same exception (code reading, not run).
> h3. Impact
> * The follower applies no further entries until it is restarted. Moving
> leadership back to an SCM it knows does not help.
> * The ring runs one replica short. In the four SCM ring of the trigger every
> remaining SCM is then needed for a quorum.
> No data is lost. A restart with the updated configuration should recover the
> SCM (argued, not run).
> h3. Reproduction
> [^TestBugMC3FollowerStuckAfterInstallNotification.java]
> ({{hadoop-ozone/integration-test}}, target path and Maven command in the
> class comment) follows the trigger on unmodified source, with purge enabled,
> a purge gap of 5 and small log segments: {{bootstrapSCM("scm4", true)}},
> leadership to scm4, one follower drops {{appendEntries}} and
> {{installSnapshot}} RPCs through Ratis' own {{CodeInjectionForTesting}} hook
> (a stand in for a partition, only timing) until scm4 has purged past the
> follower's next index, then the partition heals and leadership goes back to
> the original leader. It passes on unmodified source when the bug is present:
> {noformat}
> Leader commit 287, follower applied 53 -> 53 in 60s
> {noformat}
> The follower logged 12,483 "installation is in progress" refusals, and the
> stack of the one state machine call shows
> {{SCMStateMachine.notifyInstallSnapshotFromLeader}} (108s).
> h3. Patch
> [^MC-3-fail-install-snapshot-future-for-unknown-scm-leader.patch], against
> 424482eb9cfc4b835e1bf73bcdaa9e7d70df59f0. It also applies to master at
> 257a71ab277.
> When no peer matches, {{notifyInstallSnapshotFromLeader}} returns a future
> that fails on the install snapshot executor with {{IOException("No SCM peer
> matches leader address ...")}} instead of throwing. Ratis then clears its
> in-progress index in {{whenComplete}}, the leader retries, and the follower
> installs the snapshot once the leader is an SCM it knows. The future fails on
> the executor rather than being returned already failed, because Ratis checks
> right after the call that the install is still in progress, and an already
> failed future makes that check throw on every retry. Nothing changes when the
> leader is found, and the existing "missing leader info" branch is unchanged.
> While an unknown SCM stays leader the follower still cannot install from it,
> and Ratis retries the notification without backoff. Each retry logs one ERROR
> line on the follower ("Failed to notify StateMachine to InstallSnapshot ...
> No SCM peer matches leader address ..."). In a local mini cluster that was
> 5269 lines in 30 seconds (about 175 per second); in 47 of those retries the
> future failed before Ratis' check, which then logged an
> {{IllegalStateException}} stack on the follower and a "Failed
> InstallSnapshot" warning on the leader. This lasts until leadership moves to
> an SCM the follower knows or the follower is restarted with the new
> configuration. Teaching a running SCM about new peers is a separate change.
> Covered by {{testInstallSnapshotNotificationFromUnknownLeaderFailsFuture}} in
> the existing {{TestSCMStateMachine}}, which also checks that a known leader
> is still used for the download. Without the change it fails with the
> {{IllegalStateException}}. With it {{TestSCMStateMachine}},
> {{TestSCMHAManagerImpl}} and {{TestSCMContext}} pass (23 tests), checkstyle
> is clean. With the patch the reproduction fails: the notifications from scm4
> fail, and after leadership moves back the follower installs the snapshot from
> the known leader and catches up to the leader's commit index ({{follower
> applied 285 -> 287}}, leader commit 287).
> HDDS-16932 and HDDS-16928 describe the same Ratis in-progress state on an SCM
> follower from other triggers (a leadership change during a successful
> download, a failed install after Ratis acknowledged it); they are related,
> not duplicates. The pending apache/ozone pull request for HDDS-17205 edits
> the same {{checkState}} line (adds a message). The two changes are
> independent; whichever lands second needs a one line rebase, and this patch
> uses the same message text.
> Found by TLA+ model checking and code review of the OM and SCM Ratis state
> machine integration (leader readiness, snapshot install and log failure
> handling) under HDDS-15926, on commit
> 424482eb9cfc4b835e1bf73bcdaa9e7d70df59f0. Checked against HDDS issues and
> apache/ozone pull requests for duplicates before filing. The attached patch
> is a proposal for review. Generated with Specula (Claude Opus 5.5).
--
This message was sent by Atlassian Jira
(v10.3.26#10030026)
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]