Skip to content

cluster: reject duplicated store peer address on put#11007

Open
JaySon-Huang wants to merge 2 commits into
tikv:masterfrom
JaySon-Huang:cluster/reject-duplicate-peer-address
Open

cluster: reject duplicated store peer address on put#11007
JaySon-Huang wants to merge 2 commits into
tikv:masterfrom
JaySon-Huang:cluster/reject-duplicate-peer-address

Conversation

@JaySon-Huang

@JaySon-Huang JaySon-Huang commented Jul 14, 2026

Copy link
Copy Markdown
Contributor

What problem does this PR solve?

Issue Number: Close #11002

PD only enforced uniqueness of a store's main address during registration.
A new store could still be accepted with a unique main address but a
peer_address already used by another live store (or colliding with another
store's address). Raft prefers peer_address, so messages can be misrouted
and cause StoreNotMatch, stuck placement operators, and unavailable
TiFlash replicas.

What is changed and how does it work?

Reject store registration when a non-empty peer_address collides with
another live store's peer_address or address, and when address collides
with another live store's non-empty peer_address. Tombstone and physically
destroyed stores are still allowed to be replaced, matching the existing
main-address reuse rules. Empty peer_address (common for TiKV) is ignored.

Check List

Tests

  • Unit test

Related changes

  • Need to cherry-pick to the release branch

Release note

PD now rejects store registration when peer_address collides with another live store's address or peer_address.

Summary by CodeRabbit

  • Bug Fixes
    • Prevented store registrations from using addresses that conflict with existing store or peer addresses.
    • Added validation for both main and peer address collisions, including cross-collisions.
    • Allowed address reuse after the previous store has been physically removed or tombstoned.
    • Preserved valid updates for the same store and allowed empty peer addresses without conflicts.

Prevent two live stores from registering the same non-empty
peer_address, which can misroute Raft traffic (ref tikv#11002).

Signed-off-by: JaySon-Huang <tshent@qq.com>
Also forbid a store's address/peer_address from matching another
live store's peer_address/address to avoid Raft misrouting.

Signed-off-by: JaySon-Huang <tshent@qq.com>
@ti-chi-bot ti-chi-bot Bot added release-note Denotes a PR that will be considered when it comes time to generate release notes. do-not-merge/needs-triage-completed dco-signoff: yes Indicates the PR's author has signed the dco. labels Jul 14, 2026
@ti-chi-bot

ti-chi-bot Bot commented Jul 14, 2026

Copy link
Copy Markdown
Contributor

[APPROVALNOTIFIER] This PR is NOT APPROVED

This pull-request has been approved by:
Once this PR has been reviewed and has the lgtm label, please assign qiuyesuifeng for approval. For more information see the Code Review Process.
Please ensure that each of them provides their approval before proceeding.

The full list of commands accepted by this bot can be found here.

Details Needs approval from an approver in each of these files:

Approvers can indicate their approval by writing /approve in a comment
Approvers can cancel approval by writing /approve cancel in a comment

@ti-chi-bot ti-chi-bot Bot added the contribution This PR is from a community contributor. label Jul 14, 2026
@ti-chi-bot

ti-chi-bot Bot commented Jul 14, 2026

Copy link
Copy Markdown
Contributor

Hi @JaySon-Huang. Thanks for your PR.

I'm waiting for a tikv member to verify that this patch is reasonable to test. If it is, they should reply with /ok-to-test on its own line. Until that is done, I will not automatically test new commits in this PR, but the usual testing commands by org members will still work. Regular contributors should join the org to skip this step.

Once the patch is verified, the new status will be reflected by the ok-to-test label.

I understand the commands that are listed here.

Details

Instructions for interacting with me using PR comments are available here. If you have questions or suggestions related to my behavior, please file an issue against the kubernetes-sigs/prow repository.

@ti-chi-bot ti-chi-bot Bot added needs-ok-to-test Indicates a PR created by contributors and need ORG member send '/ok-to-test' to start testing. size/L Denotes a PR that changes 100-499 lines, ignoring generated files. labels Jul 14, 2026
@coderabbitai

coderabbitai Bot commented Jul 14, 2026

Copy link
Copy Markdown

Review Change Stack

📝 Walkthrough

Walkthrough

Store registration now rejects collisions between store addresses and non-empty peer addresses. Tests cover active, offline, destroyed, and tombstoned stores, same-store updates, empty peer addresses, and cross-collision cases.

Changes

Peer address uniqueness

Layer / File(s) Summary
Expand store conflict validation
server/cluster/cluster.go
Store insertion and update validation rejects duplicate store addresses, peer addresses, and cross-collisions while allowing comparisons for the same store ID.
Validate peer address reuse
server/cluster/cluster_test.go
TestReusePeerAddress verifies empty and same-store reuse, rejects conflicts for active or offline stores, and permits reuse after physical destruction or tombstoning.

Estimated code review effort: 3 (Moderate) | ~20 minutes

Suggested reviewers: rleungx, bufferflies

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Title check ✅ Passed The title accurately and concisely summarizes the main change: rejecting duplicate peer addresses during store registration.
Description check ✅ Passed The PR description includes the required issue reference, problem/solution sections, checklist items, and release note.
Linked Issues check ✅ Passed The code rejects live-store peer/address collisions and preserves reuse after tombstone or physical destroy, matching #11002.
Out of Scope Changes check ✅ Passed The changes are limited to the store-conflict logic and its tests, with no unrelated code paths introduced.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

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.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🧹 Nitpick comments (1)
server/cluster/cluster.go (1)

1526-1547: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Extract repeated method calls outside the loop for cleaner readability.

The loop evaluates store.GetAddress() and store.GetPeerAddress() multiple times per iteration. While these are fast inlineable field accesses, extracting them into local variables before the loop improves readability and slightly reduces redundant method calls.

💡 Proposed refactor
 	// TiFlash uses peer address for Raft replication, so a non-empty peer
 	// address must also not collide with any other store's address (and vice versa).
 	// Empty peer address is common for TiKV and should not participate in conflict checks.
+	storeAddr := store.GetAddress()
+	storePeerAddr := store.GetPeerAddress()
 	for _, s := range c.GetStores() {
 		// It's OK to start a new store on the same address if the old store has been removed or physically destroyed.
 		if s.IsRemoved() || s.IsPhysicallyDestroyed() {
 			continue
 		}
 		if s.GetID() == store.GetId() {
 			continue
 		}
 		existingAddr := s.GetAddress()
 		existingPeerAddr := s.GetMeta().GetPeerAddress()
-		if store.GetAddress() == existingAddr ||
-			(existingPeerAddr != "" && store.GetAddress() == existingPeerAddr) {
+		if storeAddr == existingAddr ||
+			(existingPeerAddr != "" && storeAddr == existingPeerAddr) {
 			return errors.Errorf("duplicated store address: %v, already registered by %v", store, s.GetMeta())
 		}
-		if store.GetPeerAddress() != "" &&
-			(store.GetPeerAddress() == existingAddr || store.GetPeerAddress() == existingPeerAddr) {
+		if storePeerAddr != "" &&
+			(storePeerAddr == existingAddr || storePeerAddr == existingPeerAddr) {
 			return errors.Errorf("duplicated store peer address: %v, already registered by %v", store, s.GetMeta())
 		}
 	}
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@server/cluster/cluster.go` around lines 1526 - 1547, In the store-address
conflict-checking logic, extract store.GetAddress() and store.GetPeerAddress()
into local variables before the loop over c.GetStores(), then use those
variables throughout the comparisons while preserving the existing
empty-peer-address behavior and errors.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Nitpick comments:
In `@server/cluster/cluster.go`:
- Around line 1526-1547: In the store-address conflict-checking logic, extract
store.GetAddress() and store.GetPeerAddress() into local variables before the
loop over c.GetStores(), then use those variables throughout the comparisons
while preserving the existing empty-peer-address behavior and errors.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: c75620a1-a43f-4f20-8e76-fa1a75912303

📥 Commits

Reviewing files that changed from the base of the PR and between 6a2787b and 9da57a2.

📒 Files selected for processing (2)
  • server/cluster/cluster.go
  • server/cluster/cluster_test.go

@codecov

codecov Bot commented Jul 14, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 79.23%. Comparing base (c2a47d8) to head (9da57a2).
⚠️ Report is 2 commits behind head on master.

Additional details and impacted files
@@           Coverage Diff           @@
##           master   #11007   +/-   ##
=======================================
  Coverage   79.22%   79.23%           
=======================================
  Files         541      541           
  Lines       75965    75991   +26     
=======================================
+ Hits        60187    60211   +24     
- Misses      11531    11548   +17     
+ Partials     4247     4232   -15     
Flag Coverage Δ
unittests 79.23% <100.00%> (+<0.01%) ⬆️

Flags with carried forward coverage won't be shown. Click here to find out more.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

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

Labels

contribution This PR is from a community contributor. dco-signoff: yes Indicates the PR's author has signed the dco. do-not-merge/needs-triage-completed needs-ok-to-test Indicates a PR created by contributors and need ORG member send '/ok-to-test' to start testing. release-note Denotes a PR that will be considered when it comes time to generate release notes. size/L Denotes a PR that changes 100-499 lines, ignoring generated files.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Reject or flag duplicate store peer addresses during store registration

1 participant