diff --git a/internal/querycoordv2/checkers/leader_checker.go b/internal/querycoordv2/checkers/leader_checker.go index 756e842d8c250..110d58068f52d 100644 --- a/internal/querycoordv2/checkers/leader_checker.go +++ b/internal/querycoordv2/checkers/leader_checker.go @@ -171,13 +171,16 @@ func (c *LeaderChecker) findNeedLoadedSegments(ctx context.Context, replica *met continue } - // when segment's version in leader view doesn't match segment's version in dist - // which means leader view store wrong segment location in leader view, then we should update segment location and segment's version + // The routing table on the delegator points to the nodes where segments are loaded. There are two scenarios that require updating the routing table on the delegator: + // 1. Missing Segment Routing - The routing table lacks the route for a specific segment. + // 2. Outdated Segment Routing - A segment has multiple copies loaded, but the routing table points to a node that does not host the most recently loaded copy. + // This ensures the routing table remains accurate and up-to-date, reflecting the latest segment distribution. version, ok := leaderView.Segments[s.GetID()] - if !ok || version.GetVersion() != s.Version { + if !ok || version.GetNodeID() != s.Node { log.RatedDebug(10, "leader checker append a segment to set", zap.Int64("segmentID", s.GetID()), zap.Int64("nodeID", s.Node)) + action := task.NewLeaderAction(leaderView.ID, s.Node, task.ActionTypeGrow, s.GetInsertChannel(), s.GetID(), time.Now().UnixNano()) t := task.NewLeaderSegmentTask( ctx, diff --git a/internal/querycoordv2/checkers/leader_checker_test.go b/internal/querycoordv2/checkers/leader_checker_test.go index ff0daaa76e66e..1d44938f7690b 100644 --- a/internal/querycoordv2/checkers/leader_checker_test.go +++ b/internal/querycoordv2/checkers/leader_checker_test.go @@ -138,22 +138,28 @@ func (suite *LeaderCheckerTestSuite) TestSyncLoadedSegments() { suite.Equal(tasks[0].Actions()[0].(*task.LeaderAction).SegmentID(), int64(1)) suite.Equal(tasks[0].Priority(), task.TaskPriorityLow) - // test segment's version in leader view doesn't match segment's version in dist - observer.dist.SegmentDistManager.Update(1, utils.CreateTestSegment(1, 1, 1, 2, 1, "test-insert-channel")) - view = utils.CreateTestLeaderView(2, 1, "test-insert-channel", map[int64]int64{}, map[int64]*meta.Segment{}) + // Verify that the segment routing table in the leader view does not point to the most recent segment replica. + // the leader view points to the segment on querynode-2, with version 1 + // the distribution shows that the segment is on querynode-1, with latest version 2 + node1, node2 := int64(1), int64(2) + version1, version2 := int64(1), int64(2) + observer.dist.SegmentDistManager.Update(node1) + observer.dist.SegmentDistManager.Update(node2, utils.CreateTestSegment(1, 1, 1, node2, version2, "test-insert-channel")) + view = utils.CreateTestLeaderView(node2, 1, "test-insert-channel", map[int64]int64{}, map[int64]*meta.Segment{}) view.TargetVersion = observer.target.GetCollectionTargetVersion(ctx, 1, meta.CurrentTarget) view.Segments[1] = &querypb.SegmentDist{ - NodeID: 0, - Version: time.Now().UnixMilli() - 1, + NodeID: node1, + Version: version1, } - observer.dist.LeaderViewManager.Update(2, view) + observer.dist.LeaderViewManager.Update(node2, view) tasks = suite.checker.Check(context.TODO()) suite.Len(tasks, 1) suite.Equal(tasks[0].Source(), utils.LeaderChecker) suite.Len(tasks[0].Actions(), 1) suite.Equal(tasks[0].Actions()[0].Type(), task.ActionTypeGrow) - suite.Equal(tasks[0].Actions()[0].Node(), int64(1)) + suite.Equal(tasks[0].Actions()[0].Node(), node2) + suite.Equal(tasks[0].Actions()[0].(*task.LeaderAction).GetLeaderID(), node2) suite.Equal(tasks[0].Actions()[0].(*task.LeaderAction).SegmentID(), int64(1)) suite.Equal(tasks[0].Priority(), task.TaskPriorityLow)