// 将一组新的节点(Master,NotFail,NoSlots)设置成一个ReplicaSet // 需要保证节点覆盖所有Region func (self *MakeReplicaSetCommand) Execute(c *cc.Controller) (cc.Result, error) { cs := c.ClusterState masterNodeId := "" masterRegion := meta.MasterRegion() regions := meta.AllRegions() regionExist := map[string]bool{} for _, r := range regions { regionExist[r] = false } // 检查节点状态 for _, nodeId := range self.NodeIds { node := cs.FindNode(nodeId) if node == nil { return nil, ErrNodeNotExist } if node.Fail { return nil, fmt.Errorf("Node %s has failed", nodeId) } if !node.IsMaster() { return nil, fmt.Errorf("Node %s is not master, newly added node must be master.", nodeId) } if len(node.Ranges) != 0 { return nil, fmt.Errorf("Node %s is not empty, newly added node must be empty.", nodeId) } regionExist[node.Region] = true if node.Region == masterRegion { masterNodeId = nodeId } } // 检查地域覆盖 for region, exist := range regionExist { if exist == false { return nil, fmt.Errorf("Lack node in region %s", region) } } // 设置主从关系 for _, nodeId := range self.NodeIds { if nodeId == masterNodeId { continue } node := cs.FindNode(nodeId) _, err := redis.ClusterReplicate(node.Addr(), masterNodeId) if err != nil { return nil, fmt.Errorf("Set REPLICATE failed(%v), please set relationship manually.", err) } } return nil, nil }
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 }