func GenerateRebalancePlan(method string, cluster *topo.Cluster, targetIds []string, ratio int) ([]*MigratePlan, error) { rss := cluster.ReplicaSets() regions := meta.AllRegions() ss := []*topo.Node{} // 有slots的Master tm := map[string]*topo.Node{} // 空slots的Master for _, rs := range rss { master := rs.Master // 忽略主挂掉和region覆盖不全的rs if master.Fail || !rs.IsCoverAllRegions(regions) || master.Free { continue } if master.Empty() { tm[master.Id] = master } else { ss = append(ss, master) } } if method == "mergetail" { merger := MergerTable[method] if merger == nil { return nil, fmt.Errorf("Rebalancing method %s not exist.", method) } plans := merger(ss, 0) return plans, nil } else if method == "mergeall" { merger := MergerTable[method] if merger == nil { return nil, fmt.Errorf("Rebalancing method %s not exist.", method) } plans := merger(ss, ratio) return plans, nil } else { var ts []*topo.Node // 如果没传TargetId,则选择所有可以作为迁移目标的rs if len(targetIds) == 0 { for _, node := range tm { ts = append(ts, node) } } else { for _, id := range targetIds { if tm[id] == nil { return nil, fmt.Errorf("Master %s not found.", id) } ts = append(ts, tm[id]) } } if len(ts) == 0 { return nil, fmt.Errorf("No available empty target replicasets.") } rebalancer := RebalancerTable[method] if rebalancer == nil { return nil, fmt.Errorf("Rebalancing method %s not exist.", method) } plans := rebalancer(ss, ts) return plans, nil } return nil, nil }