Skip to content

Cluster Bus v2 - Decentralized Failure Detector - #4127

Open
sushilpaneru1 wants to merge 6 commits into
valkey-io:cluster-v2from
sushilpaneru1:cluster-v2-failure-detector
Open

Cluster Bus v2 - Decentralized Failure Detector#4127
sushilpaneru1 wants to merge 6 commits into
valkey-io:cluster-v2from
sushilpaneru1:cluster-v2-failure-detector

Conversation

@sushilpaneru1

@sushilpaneru1 sushilpaneru1 commented Jul 9, 2026

Copy link
Copy Markdown
Contributor

Closes #3862

Implements a decentralized failure detection mechanism for multi-node shard that uses the replication stream (data-path) rather than relying solely on the centralized AE_ACK-based detector on the raft leader. For multi-node shard, this provides reliable signal on the actual replication health.

The failure detector uses two complementary mechanisms (either of - Centralized or decentralized):

  • Shard-level (replica ↔ primary): Primary and replica detect each other via the replication stream. The primary monitors repl_ack_time for connected replicas and tracks repl_unconnected_since for disconnected ones. The replica monitors last_interaction or repl_down_since for its primary. Asymmetric timeouts (T for primary, 1.5T for replica) ensure the primary proposes NODE_FAIL first.
  • Cluster-level (leader → whole shard): the raft leader detects a shard via AE_ACK when no member of that shard is responsive.

In case where shard nodes can't reach each other but can be reached by raft leader, replica will get marked NODE_FAIL by the primary as this replica is of no use to primary.

Testing

./runtest --verbose --dump-logs --cluster-raft --single tests/unit/cluster/

Test Summary: 497 passed, 0 failed

\o/ All tests passed without errors!

Cleanup: may take some time... OK

@coderabbitai

coderabbitai Bot commented Jul 9, 2026

Copy link
Copy Markdown

Important

Review skipped

Auto reviews are disabled on base/target branches other than the default branch.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro Plus

Run ID: ee4fc7f7-7f80-4c28-9226-506423a71293

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

Signed-off-by: Sushil Paneru <sushil.paneru1@gmail.com>
@sushilpaneru1
sushilpaneru1 force-pushed the cluster-v2-failure-detector branch from e02768f to c9d6698 Compare July 9, 2026 07:27
@sushilpaneru1
sushilpaneru1 marked this pull request as draft July 9, 2026 07:31

@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.

I found a few correctness issues in the new failure detector. The main ones are that the apply-time validator is still too permissive, and the new timestamp handling can mark healthy replicas failed during sync or after a transient reconnect.

Comment thread src/cluster_raft.c Outdated
Comment thread src/cluster_raft.c Outdated
Comment thread src/cluster_raft.c Outdated
Comment thread src/cluster_raft.c
Signed-off-by: Sushil Paneru <sushil.paneru1@gmail.com>
@sushilpaneru1
sushilpaneru1 force-pushed the cluster-v2-failure-detector branch from 28bb1b2 to 37c330e Compare July 9, 2026 19:53
Signed-off-by: Sushil Paneru <sushil.paneru1@gmail.com>
Signed-off-by: Sushil Paneru <sushil.paneru1@gmail.com>
@sushilpaneru1
sushilpaneru1 marked this pull request as ready for review July 13, 2026 00:34
@murphyjacob4
murphyjacob4 self-requested a review July 25, 2026 00:16
Comment thread design-docs/cluster-raft.md Outdated
Comment on lines +493 to +500
2. **NODE_FAIL for single-node shards**: for shards with no replicas,
there is no replication stream to monitor. If a peer hasn't
responded within `cluster-node-timeout`, the leader proposes
NODE_FAIL. When the node comes back and sends AE_ACK, the leader
proposes NODE_RECOVER.

**Whole-shard-down fallback:** When ALL members of a multi-node shard
have timed out on the leader's AE_ACK tracking, no shard member is

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.

nit: Aren't these actually the same thing?

Just when there are no replicas, whole shard = 1 node.

I guess conceptually aligning these two may be useful. So we only have two modes of failure:

  1. Shard-level Replica <-> Primary detection
  2. Cluster-level Leader <-> (whole shard) detection

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Yes you are right, will simplify the doc.

Comment thread src/cluster_raft.c
Comment on lines +56 to +59
/* Grace period (ms) before proposing NODE_FAIL for a replica that is not in
* server.replicas. After a topology change (FAILOVER/SET_REPLICA_OF), a
* healthy replica needs time to establish its replication connection. */
#define REPL_CONNECT_GRACE_PERIOD_MS 5000

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.

Maybe max(5000, server.cluster_node_timeout)?

Comment thread design-docs/cluster-raft.md Outdated
Mark a node as failed. Proposed by a shard member via the
replication-stream detector, or by the raft leader via AE_ACK
for single-node shards and whole-shard-down fallback. The
proposer field enables apply-time validation (see Failure

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.

Did I miss where apply-time validation is in the doc? I see that we describe it in NODE_RECOVER but this points to Failure Detection

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

there was dangling reference, updated the doc.

Comment thread src/cluster_raft.c Outdated
if (node && node != myself) {
clusterNode *node = NULL;
clusterNode *proposer = NULL;
int valid_proposer = raftValidateFailRecoverEntry(e->data, &node, &proposer);

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.

Aren't we subject to this style of failure?

  • R proposes FAILOVER
  • P proposes NODE_FAIL R
  • R is promoted to primary, P is demoted to replica. Shard epoch bumps to E+1
  • The stale NODE_FAIL R (proposed by P) is applied next.
  • The proposer validator sees P is a replica, and R is a primary. Since replica_and_primary is valid (a replica can fail its primary), it applies the failure, marking the new primary R as failed.

I think it would be trivially provable if we just made NODE_FAIL check (but not bump) on the epoch. If we do that, I don't think we actually need apply-time proposer validation. We could do the proposer validation at proposal time, and let the epoch ensure there is no conflicting changes that would invalidate that proposal time check.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Good catch. I have added epoch validation in apply time and proposer validation in proposal time. But for NODE_RECOVER I don't think we should do epoch validation. It can cause legitimate recovery to be delayed, causing availability regression on replicas.

Signed-off-by: Sushil Paneru <sushil.paneru1@gmail.com>
@sushilpaneru1
sushilpaneru1 force-pushed the cluster-v2-failure-detector branch from c0fd464 to eede0d7 Compare July 27, 2026 17:59
Signed-off-by: Sushil Paneru <sushil.paneru1@gmail.com>
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.

2 participants