[ 
https://issues.apache.org/jira/browse/HDDS-16804?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel
 ]

Siyao Meng updated HDDS-16804:
------------------------------
    Attachment: TestBugMC5NewLeaderCommandLost.java

> ReplicationSupervisor loses a command of the new SCM leader when an equal 
> task of the previous leader is still queued
> ---------------------------------------------------------------------------------------------------------------------
>
>                 Key: HDDS-16804
>                 URL: https://issues.apache.org/jira/browse/HDDS-16804
>             Project: Apache Ozone
>          Issue Type: Bug
>            Reporter: Siyao Meng
>            Priority: Minor
>         Attachments: 
> MC-5-run-new-scm-leader-command-when-queued-duplicate-is-dropped.patch, 
> TestBugMC5NewLeaderCommandLost.java
>
>
> h3. Mechanism
> {{ReplicationSupervisor.addToQueue}} drops a task when an equal one is 
> already in {{inFlight}}. Task equality does not include the SCM term: 
> {{ReconcileContainerTask}} compares the container ID (HDDS-13086), 
> {{ECReconstructionCoordinatorTask}} the container ID, {{ReplicationTask}} the 
> container ID and the target. When a queued task gets a thread, 
> {{TaskRunner.run}} drops it if its term is older than the datanode's current 
> SCM term ("Ignoring ... since SCM leader has new term", HDDS-7620). The two 
> rules do not compose: a command of the new leader that arrives while the 
> equal task of the old leader is still queued is dropped as a duplicate, and 
> the queued task is then dropped for its term. Neither runs. The datanode term 
> is already advanced in {{StateContext.addCommand}} when the new command 
> reaches the supervisor.
> h3. Trigger
> # All threads of the supervisor are busy 
> ({{hdds.datanode.replication.streams.limit}}, 10 by default, shared by the 
> three task types unless per volume pools are enabled) and a task sent by the 
> SCM leader of term N waits in its queue.
> # SCM leadership changes.
> # The new leader sends an equal command (same container for reconcile and EC 
> reconstruction, same container and target for replication) before the queued 
> task gets a thread.
> # The queued task gets a thread and is dropped for its term.
> For reconcile, step 3 means the request is issued again through the new 
> leader ({{ozone admin container reconcile}}), because SCM sends reconcile 
> commands only on request. For replication and EC reconstruction, step 3 means 
> the old task is still queued when the new leader's ReplicationManager starts 
> ({{hdds.scm.wait.time.after.safemode.exit}}, default 5m, after it becomes 
> ready as leader) and the new leader chooses this datanode again with the same 
> source and target or as coordinator of the same container (read from the 
> code, not run).
> h3. Impact
> * Reconcile: the container is not reconciled on that datanode although both 
> requests were accepted. SCM does not send the command again, so it stays that 
> way until somebody repeats the request. The only trace is the INFO line on 
> the datanode.
> * Replication and EC reconstruction: the new leader's command is lost on the 
> datanode in the same way (run). The new leader's pending operation expires 
> after {{hdds.scm.replication.event.timeout}} (default 12m) and 
> ReplicationManager sends the command again on a later pass 
> ({{hdds.scm.replication.thread.interval}}, default 300s), so the effect is a 
> delayed repair (read from the code, not run).
> * No data is affected. A task that is already running when the new command 
> arrives is not affected.
> h3. Reproduction
> PASS, deterministic, unmodified source. 
> [^TestBugMC5NewLeaderCommandLost.java] ({{hadoop-hdds/container-service}}) 
> sends 11 commands of term 1 and then 11 commands of term 2 for the same 
> containers through {{StateContext.addCommand}}, 
> {{StateContext.getNextCommand}} and the real command handler into a 
> {{ReplicationSupervisor}} with default settings. Only the component that does 
> the work (container controller, push replicator, EC reconstruction 
> coordinator) is a stand in that counts its calls and keeps running tasks open 
> until released. For each of the three command types the 11th container is 
> processed 0 times after two commands, and the supervisor logs "Ignoring 
> QUEUED ... since SCM leader has new term (1 < 2)". A control with duplicates 
> in the same term processes every container once. A passing test means the 
> defect is present. Not run on a cluster with a real SCM failover.
> h3. Patch
> [^MC-5-run-new-scm-leader-command-when-queued-duplicate-is-dropped.patch], 
> against 1e528b97aed3eef1be6846f1f0767c1ef98a883a. It also applies to master 
> at 8ca44914771.
> {{ReplicationSupervisor}} keeps, for each task in flight, the equal command 
> it received last. When a task is dropped without running and a command of a 
> newer term was received for it meanwhile, that command is queued. Tasks of an 
> obsolete term are still dropped and a duplicate of a running task is still 
> dropped, so there is at most one of any set of equal tasks, as before. Not 
> changed by this patch: a later command of the same term that is deduplicated 
> against a queued task which then passes its deadline is still dropped 
> (replication and EC reconstruction only, reconcile commands carry no 
> deadline). Adding the term to the task equality is not an alternative: with 
> the term in {{ReconcileContainerCommand.equals}} the supervisor accepts the 
> new leader's command next to a reconciliation of the same container that is 
> still running (run), which is what HDDS-13086 removed.
> Covered by two tests in the existing {{TestReplicationSupervisor}}. 
> {{commandOfNewLeaderRunsWhenQueuedTaskOfOldLeaderIsDropped}} fails without 
> the change because the new leader's command never runs. 
> {{commandOfNewLeaderIsDeduplicatedAgainstRunningTask}} passes with and 
> without it and pins that a running task gets no second run. With the patch 
> {{TestReplicationSupervisor}} (56 tests) and the command handler, 
> {{StateContext}}, {{DatanodeStateMachine}} and replication unit suites (130 
> tests in total) pass, checkstyle is clean. With the patch the reproduction 
> fails for all three command types because every container is processed. 
> {{TestContainerReplication}} (16 tests on a mini cluster) passes with the 
> patch.
> Found by TLA+ model checking and code review of the container reconciliation 
> paths in the datanode and SCM under HDDS-15926, on commit 
> 1e528b97aed3eef1be6846f1f0767c1ef98a883a. 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
(v8.20.10#820010)

---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to