Skip to content

Add AZ_AFFINITY_ALL_NODES read policy - #6721

Draft
sz-armin wants to merge 7 commits into
valkey-io:mainfrom
sz-armin:feature/az-affinity-all-nodes
Draft

Add AZ_AFFINITY_ALL_NODES read policy#6721
sz-armin wants to merge 7 commits into
valkey-io:mainfrom
sz-armin:feature/az-affinity-all-nodes

Conversation

@sz-armin

@sz-armin sz-armin commented Aug 6, 2026

Copy link
Copy Markdown

Summary

We add the AZ_AFFINITY_ALL_NODES read policy, which unlike AZ_AFFINITY_REPLICAS_AND_PRIMARY does not prioritize replicas before the primary.

Issue link

Closes #6653

Features / Behaviour Changes

  • AZ_AFFINITY_ALL_NODES read policy is added to both the core and Python wrapper
  • Small fixes:
    • get_next_local_replica now uses try_get_connection to avoid blocking on mid-reconnect nodes.
    • Added the missing "AllNodes" arm to create_client_from_uri read_from parser.

Implementation

Most of the implementation follows a similar pattern to the existing policies, and should be mostly isolated from existing functionality, except for the two fixes mentioned above.

Additionally, our new policy makes sure explicit replica routes stay replicas-only, which is unlike the current AZ_AFFINITY_REPLICAS_AND_PRIMARY which could potentially end up sending such requests to a primary.

Limitations

  • This PR only covers core and the Python wrapper. Support for other wrappers would follow after current changes are confirmed/merged.

Testing

  • Tests are added following the existing patterns and confirmed passing.
  • Happy path routing has been tested in a local cluster.

Checklist

Before submitting the PR make sure the following are checked:

  • This Pull Request is related to one issue.
  • Commit message has a detailed description of what changed and why.
  • We have avoided overly verbose commit messages as they seemed unnecessary for the current changes.
  • Tests are added or updated.
  • CHANGELOG.md and documentation files are updated.
  • valkey-glide-docs updates to follow once the direction and details are confirmed to be acceptable.
  • Linters have been run (make *-lint targets) and Prettier has been run (make prettier-fix).
  • Destination branch is correct - main or release
  • Create merge commit if merging release branch into main, squash otherwise.
  • We are not dealing with a release branch.
  • Make sure to update the documentation in the valkey-glide-docs repository if necessary
  • valkey-glide-docs updates to follow once the direction and details are confirmed to be acceptable.

Signed-off-by: sz-armin <77587091+sz-armin@users.noreply.github.com>
Signed-off-by: sz-armin <77587091+sz-armin@users.noreply.github.com>
Signed-off-by: sz-armin <77587091+sz-armin@users.noreply.github.com>
Signed-off-by: sz-armin <77587091+sz-armin@users.noreply.github.com>
Signed-off-by: sz-armin <77587091+sz-armin@users.noreply.github.com>
Signed-off-by: sz-armin <77587091+sz-armin@users.noreply.github.com>

@valkey-review-bot valkey-review-bot Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The new policy's ordinary command routing is covered, but one existing core path bypasses that routing and can send replica-required work to a primary.

// behavior of these strategies when no local node is known.
ReadFromReplicaStrategy::AZAffinity(_az) => round_robin_replica(),
ReadFromReplicaStrategy::AZAffinityReplicasAndPrimary(_az) => round_robin_all_nodes(),
ReadFromReplicaStrategy::AZAffinityAllNodes(_az) => round_robin_all_nodes(),

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Preserve ReplicaRequired here instead of applying the all-node fallback unconditionally. Cluster scan calls node_address_for_slot(..., SlotAddr::ReplicaRequired) (commands/cluster_scan.rs:555-560), and ReplicaRequired explicitly means a replica if one exists (cluster_routing.rs:1341-1343); this arm can now select the primary on every rotation even when replicas exist. Branch on slot_addr so AZAffinityAllNodes uses round_robin_replica() for required-replica routes and round_robin_all_nodes() only for optional reads.

@sz-armin sz-armin Aug 6, 2026

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We basically have two options for ReplicaRequired:

  1. Respect it on both the main read path and the slot-map path (i.e. replica-only here)

The cleaner fix, though it differs from how e.g. AZ_AFFINITY_REPLICAS_AND_PRIMARY handles this path.

  1. Use all nodes on both paths for consistency

However that would replicate what looks like a bug, and the existing strategies don't seem to agree with each other anyway (e.g. ALL_NODES is already replica-only for ReplicaRequired in lookup_route but not in the slot map).


Since this PR already handles the main path as replica-only, I went with 1 here too. Happy to revert if consistency is preferred.

When no local node is known, ReplicaRequired routes under the
AZAffinityAllNodes strategy now use replica rotation instead of falling
back to all nodes, matching the strategy's lookup_route behavior.

Signed-off-by: sz-armin <77587091+sz-armin@users.noreply.github.com>
@sz-armin
sz-armin force-pushed the feature/az-affinity-all-nodes branch from e584ef6 to 29caa2a Compare August 6, 2026 09:21
@xShinnRyuu xShinnRyuu self-assigned this Aug 7, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

New ReadFrom strategy: equal round-robin across all in-AZ nodes

2 participants