diff --git a/pkg/utils/etcdutil/etcdutil.go b/pkg/utils/etcdutil/etcdutil.go index ab18ca01859..4c5de31685b 100644 --- a/pkg/utils/etcdutil/etcdutil.go +++ b/pkg/utils/etcdutil/etcdutil.go @@ -33,6 +33,7 @@ import ( "github.com/tikv/pd/pkg/utils/logutil" "github.com/tikv/pd/pkg/utils/syncutil" "github.com/tikv/pd/pkg/utils/typeutil" + "go.etcd.io/etcd/api/v3/etcdserverpb" "go.etcd.io/etcd/api/v3/mvccpb" "go.etcd.io/etcd/api/v3/v3rpc/rpctypes" etcdtypes "go.etcd.io/etcd/client/pkg/v3/types" @@ -119,12 +120,17 @@ func ListEtcdMembers(ctx context.Context, client *clientv3.Client) (*clientv3.Me time.Sleep(time.Duration(d) * time.Second) }) newCtx, cancel := context.WithTimeout(ctx, DefaultRequestTimeout) - listResp, err := client.MemberList(newCtx) + // After the etcd server is upgraded to v3.5.0, the MemberList API will return the member list in a linearizable way by default. + // It is introduced by https://github.com/etcd-io/etcd/pull/11639 + // If Linearizable is set to false, the member list will be returned with server's local data. + // If Linearizable is set to true, it is served with linearizable guarantee. If the server is disconnected from quorum, `MemberList` call will fail. + c := clientv3.RetryClusterClient(client) + resp, err := c.MemberList(newCtx, &etcdserverpb.MemberListRequest{Linearizable: false}) cancel() if err != nil { - return listResp, errs.ErrEtcdMemberList.Wrap(err).GenWithStackByCause() + return (*clientv3.MemberListResponse)(resp), errs.ErrEtcdMemberList.Wrap(err).GenWithStackByCause() } - return listResp, nil + return (*clientv3.MemberListResponse)(resp), nil } // RemoveEtcdMember removes a member by the given id.