From 56ae35bc9bb7a1cd0c8c282a7623927e80ad0782 Mon Sep 17 00:00:00 2001 From: pingcap-github-bot Date: Sun, 28 Jun 2020 16:08:32 +0800 Subject: [PATCH] Associate each region with an independent backoffer (#17568) (#17583) Signed-off-by: sre-bot Co-authored-by: Xintao Co-authored-by: ti-srebot <66930949+ti-srebot@users.noreply.github.com> --- store/tikv/coprocessor.go | 22 ++++++++++++++++++---- 1 file changed, 18 insertions(+), 4 deletions(-) diff --git a/store/tikv/coprocessor.go b/store/tikv/coprocessor.go index 4bbd3053284ea..46ffa9198e365 100644 --- a/store/tikv/coprocessor.go +++ b/store/tikv/coprocessor.go @@ -471,8 +471,7 @@ func (worker *copIteratorWorker) run(ctx context.Context) { respCh = task.respChan } - bo := NewBackoffer(ctx, copNextMaxBackoff).WithVars(worker.vars) - worker.handleTask(bo, task, respCh) + worker.handleTask(ctx, task, respCh) close(task.respChan) select { case <-worker.finishCh: @@ -627,8 +626,20 @@ func (it *copIterator) Next(ctx context.Context) (kv.ResultSubset, error) { return resp, nil } +// Associate each region with an independent backoffer. In this way, when multiple regions are +// unavailable, TiDB can execute very quickly without blocking +func chooseBackoffer(ctx context.Context, backoffermap map[uint64]*Backoffer, task *copTask, worker *copIteratorWorker) *Backoffer { + bo, ok := backoffermap[task.region.id] + if ok { + return bo + } + newbo := NewBackoffer(ctx, copNextMaxBackoff).WithVars(worker.vars) + backoffermap[task.region.id] = newbo + return newbo +} + // handleTask handles single copTask, sends the result to channel, retry automatically on error. -func (worker *copIteratorWorker) handleTask(bo *Backoffer, task *copTask, respCh chan<- *copResponse) { +func (worker *copIteratorWorker) handleTask(ctx context.Context, task *copTask, respCh chan<- *copResponse) { defer func() { r := recover() if r != nil { @@ -641,8 +652,11 @@ func (worker *copIteratorWorker) handleTask(bo *Backoffer, task *copTask, respCh } }() remainTasks := []*copTask{task} + backoffermap := make(map[uint64]*Backoffer) for len(remainTasks) > 0 { - tasks, err := worker.handleTaskOnce(bo, remainTasks[0], respCh) + curTask := remainTasks[0] + bo := chooseBackoffer(ctx, backoffermap, curTask, worker) + tasks, err := worker.handleTaskOnce(bo, curTask, respCh) if err != nil { resp := &copResponse{err: errors.Trace(err)} worker.sendToRespCh(resp, respCh, true)