From c59833429baf5e9489b271584551c18a1ec15683 Mon Sep 17 00:00:00 2001 From: Lucas Date: Wed, 11 Jan 2023 14:15:36 +0800 Subject: [PATCH] Bug fix: fix the Round-Robin algorithm when "ReadMode == ReplicaReadMixed". (#663) Signed-off-by: Lucasliang --- internal/locate/region_request.go | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/internal/locate/region_request.go b/internal/locate/region_request.go index 31d6e37756..229de5eb56 100644 --- a/internal/locate/region_request.go +++ b/internal/locate/region_request.go @@ -523,15 +523,16 @@ type accessFollower struct { } func (state *accessFollower) next(bo *retry.Backoffer, selector *replicaSelector) (*RPCContext, error) { + replicaSize := len(selector.replicas) if state.lastIdx < 0 { if state.tryLeader { - state.lastIdx = AccessIndex(rand.Intn(len(selector.replicas))) + state.lastIdx = AccessIndex(rand.Intn(replicaSize)) } else { - if len(selector.replicas) <= 1 { + if replicaSize <= 1 { state.lastIdx = state.leaderIdx } else { // Randomly select a non-leader peer - state.lastIdx = AccessIndex(rand.Intn(len(selector.replicas) - 1)) + state.lastIdx = AccessIndex(rand.Intn(replicaSize - 1)) if state.lastIdx >= state.leaderIdx { state.lastIdx++ } @@ -547,8 +548,13 @@ func (state *accessFollower) next(bo *retry.Backoffer, selector *replicaSelector state.lastIdx++ } - for i := 0; i < len(selector.replicas) && !state.option.leaderOnly; i++ { - idx := AccessIndex((int(state.lastIdx) + i) % len(selector.replicas)) + for i := 0; i < replicaSize && !state.option.leaderOnly; i++ { + idx := AccessIndex((int(state.lastIdx) + i) % replicaSize) + // If the given store is abnormal to be accessed under `ReplicaReadMixed` mode, we should choose other followers or leader + // as candidates to serve the Read request. Meanwhile, we should make the choice of next() meet Uniform Distribution. + for cnt := 0; cnt < replicaSize && !state.isCandidate(idx, selector.replicas[idx]); cnt++ { + idx = AccessIndex((int(idx) + rand.Intn(replicaSize)) % replicaSize) + } if state.isCandidate(idx, selector.replicas[idx]) { state.lastIdx = idx selector.targetIdx = idx