Skip to content

AMM: Remember replication requests that take longer than 2s #5759

Open

Description

@crusaderky

State of the art

The current AMM design is as follows:

  1. The AMM runs all registered policies
  2. Each policy issues drop or replicate suggestions
  3. The AMM assigns each suggestion to specific workers.
    Workers with the least allocated memory are the first to be chosen as recipients for replication.
    Workers with the most allocated memory are the first to be chosen as targets for dropping redundant replicas.
  4. The amount of allocated memory on each worker is estimated as actual reported memory + sum of the suggestions taken so far in the current AMM run
  5. After all the policies have yielded their suggestions, the AMM sends them in bulk to the workers.
  6. Drop suggestions are enacted immediately scheduler-side; workers may later inform the scheduler that they rejected the suggestion.
  7. After 2 seconds (configurable), the AMM runs again. Any replicate commands that are still in transit have been forgotten and will be issued anew if still applicable, potentially choosing a different target.

This design works well under the important assumption that either

  • most replications take less than 2 seconds to complete, OR
  • nothing besides the AMM transfers or generates memory that substantially tilt the balance of the cluster

On a busy cluster, where tasks run produce/destroy large amounts of memory in a non-homogeneous fashion across the cluster, then the AMM will re-issue the replicate commands that didn't complete yet from the last time and will potentially choose a different target, thus

  1. exacerbating a situation where network comms already constitute a bottleneck, and
  2. eventually generating multiple, unnecessary extra replicas of the data. These extra replicas will be later cleaned up by the ReduceReplicas policy, if it's enabled.

Notably, if the AMM is disabled (which, today, is the default), then retire_workers will spawn a temporary instance of it with only the RetireWorker policy in it; there won't be a ReduceReplicas running to clear up accidental duplicates created as described above.

Workaround

Users could increase the AMM interval to a duration that is longer than most of their network comms. This requires some finesse and it will cause a degradation in the usefulness of the AMM.

Proposed design

Add a second, longer configurable timer to AMM, e.g. replicate-timeout: 30s.
At the end of every AMM run, record the issued replicate suggestions together with their timestamp.
At the beginning of the next AMM run,

  • silently forget the suggestions that were completed successfully
  • silently forget the suggestions for keys that are no longer in memory anywhere
  • silently forget the suggestions where the recipient worker is no longer there or has entered paused or retiring status
  • loudly forget (log a warning) the suggestions older than the timeout that are not completed yet. They still may get completed in the future, as there's no way to cancel them
  • add the surviving suggestions to the memory estimate for the new run, as if they had been just issued

Cost

The proposed solution cost is O(n) (scales linearly) to the number of tasks being replicated. The total number of tasks on the cluster is inconsequential.

CC @fjetter @gjoseph92

Activity

  1. self-assigned this
    on Feb 4, 2022
  2. gjoseph92 commented on Feb 4, 2022

    @gjoseph92
    Collaborator

    Overall, this sounds good to me.

    Possible thing to add: on every AMM run, we look up the key of each new replicate suggestion in our record of old suggestions. If the target worker of the new suggestion doesn't match the target worker of the old suggestion (and we know the old suggestion is still active, since it hasn't been dropped by the rules above), then we... log a warning? Assuming the record of old suggestions is a dict, this should also be O(n) I think.

    The proposed solution cost is O(n) (scales linearly) to the number of tasks being replicated.

    When the number of tasks being replicated approaches the total number of tasks (a large sacle-down event?), should we have some sort of upper-bound/"release valve" where we avoid this check? Or is that actually when this check is the most important? With enormous scaling changes, I'm not sure if this is more or less relevant.

  3. crusaderky commented on Feb 4, 2022

    @crusaderky
    CollaboratorAuthor

    Possible thing to add: on every AMM run, we look up the key of each new replicate suggestion in our record of old suggestions. If the target worker of the new suggestion doesn't match the target worker of the old suggestion (and we know the old suggestion is still active, since it hasn't been dropped by the rules above), then we... log a warning? Assuming the record of old suggestions is a dict, this should also be O(n) I think.

    There is already logic in the various policies and in find_recipient() to consider previous suggestions earlier within the same AMM run. This change would just add the suggestion from previous runs to them.

    When the number of tasks being replicated approaches the total number of tasks (a large sacle-down event?), should we have some sort of upper-bound/"release valve" where we avoid this check? Or is that actually when this check is the most important? With enormous scaling changes, I'm not sure if this is more or less relevant.

    If you, say, retire 95% of your cluster and you suddenly need to transfer several terabytes of data over the network, it is exactly where these issues are most likely to happen. I think that the increased CPU time for the scheduler should be very mild in proportion to everything else going on (just think about the events coming from the workers).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions